diff --git a/Doc/doxygen/DoxyfileBootCommander b/Doc/doxygen/DoxyfileBootCommander index bc582527..68b703f4 100644 --- a/Doc/doxygen/DoxyfileBootCommander +++ b/Doc/doxygen/DoxyfileBootCommander @@ -38,7 +38,7 @@ PROJECT_NAME = "BootCommander - Reference Manual" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.1.0 +PROJECT_NUMBER = 1.2.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/Doc/doxygen/DoxyfileLibOpenBLT b/Doc/doxygen/DoxyfileLibOpenBLT index 2b746ce2..d6567373 100644 --- a/Doc/doxygen/DoxyfileLibOpenBLT +++ b/Doc/doxygen/DoxyfileLibOpenBLT @@ -38,7 +38,7 @@ PROJECT_NAME = "OpenBLT Host Library - Reference Manual" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.1.0 +PROJECT_NUMBER = 1.2.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/Doc/doxygen/DoxyfileOpenBLT b/Doc/doxygen/DoxyfileOpenBLT index 7cffbcaa..7791e3d5 100644 --- a/Doc/doxygen/DoxyfileOpenBLT +++ b/Doc/doxygen/DoxyfileOpenBLT @@ -38,7 +38,7 @@ PROJECT_NAME = "OpenBLT Bootloader - Reference Manual" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.4.1 +PROJECT_NUMBER = 1.4.2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/Host/BootCommander.exe b/Host/BootCommander.exe index 87ebb173..9b0e9b2d 100644 Binary files a/Host/BootCommander.exe and b/Host/BootCommander.exe differ diff --git a/Host/Source/BootCommander/CMakeLists.txt b/Host/Source/BootCommander/CMakeLists.txt index 0e5d6754..e4795205 100644 --- a/Host/Source/BootCommander/CMakeLists.txt +++ b/Host/Source/BootCommander/CMakeLists.txt @@ -69,6 +69,7 @@ endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES ) set(LIBOPENBLT_INC ${PROJECT_SOURCE_DIR}/../LibOpenBLT) set(LIBOPENBLT_LIB ${PROJECT_OUTPUT_DIRECTORY}) + #**************************************************************************************** # Compiler flags #**************************************************************************************** @@ -105,11 +106,11 @@ set( ${INCS} ) -# Set library name. When GNU GCC is used, the name to the static library file is used, -# otherwise the shared library is used by default. This works fine too, but the static -# library makes it a bit easier to move the target executable around on the file system. -if(CMAKE_C_COMPILER_ID MATCHES GNU) - set (LIBOPENBLT_LIBNAME libopenblt.a) +# Set library name of the OpenBLT Host Library +if(CMAKE_C_COMPILER_ID MATCHES MSVC) + # When building LibOpenBLT with Microsoft Visual Studio, "lib" was added to the name + # of the DLL. This needs to be done as well when linking the library. + set (LIBOPENBLT_LIBNAME libopenblt) else() set (LIBOPENBLT_LIBNAME openblt) endif() @@ -124,8 +125,19 @@ add_executable( ${PROG_SRCS} ) -# Add libraries -target_link_libraries(BootCommander ${LIBOPENBLT_LIBNAME}) +# Add libraries. Note that when compiling with GNU GCC the path of the executable is +# added to the run-time search path for libraries. This way LibOpenBLT's shared +# object file (.so) does not have to be installed in the Linux's library path as long +# as it is located in the same directory as BootCommander's executable. +if(CMAKE_C_COMPILER_ID MATCHES GNU) + # According to the CMake docs, item names starting with '-', but not '-l' or + # '-framework', are treated as linker flags. This means "-Wl" type linker flags can be + # specified here. + target_link_libraries(BootCommander ${LIBOPENBLT_LIBNAME} "-Wl,-rpath,.") +elseif(CMAKE_C_COMPILER_ID MATCHES MSVC) + target_link_libraries(BootCommander ${LIBOPENBLT_LIBNAME}) +endif() + # Only generate the PC-lint taget if the option is enabled. Use "make BootCommander_LINT" # to lint the project sources diff --git a/Host/Source/BootCommander/main.c b/Host/Source/BootCommander/main.c index f2a8d4e0..8a45ef19 100644 --- a/Host/Source/BootCommander/main.c +++ b/Host/Source/BootCommander/main.c @@ -160,8 +160,13 @@ int main(int argc, char const * const argv[]) appTransportType); /* Extract the firmware filename from the command line. */ appFirmwareFile = ExtractFirmwareFileFromCommandLine(argc, argv); + /* Note that the transport settings are allowed to be NULL in case of + * BLT_TRANSPORT_XCP_V10_USB. + */ + bool appTransportSettingsOkay = (appTransportType == BLT_TRANSPORT_XCP_V10_USB) ? + true : (appTransportSettings != NULL); /* Check the settings that were detected so far. */ - if ( (appSessionSettings == NULL) || (appTransportSettings == NULL) || + if ( (appSessionSettings == NULL) || (!appTransportSettingsOkay) || (appFirmwareFile == NULL) ) { /* Display program info */ @@ -430,7 +435,7 @@ int main(int argc, char const * const argv[]) static void DisplayProgramInfo(void) { printf("--------------------------------------------------------------------------\n"); - printf("BootCommander version 1.01. Performs firmware updates on a microcontroller\n"); + printf("BootCommander version 1.02. Performs firmware updates on a microcontroller\n"); printf("based system that runs the OpenBLT bootloader.\n\n"); printf("Copyright (c) 2017 by Feaser http://www.feaser.com\n"); printf("-------------------------------------------------------------------------\n"); @@ -454,6 +459,7 @@ static void DisplayProgramUsage(void) printf(" -t=[name] Name of the communication transport layer:\n"); printf(" xcp_rs232 (default) -> XCP on RS232.\n"); printf(" xcp_can -> XCP on CAN.\n"); + printf(" xcp_usb -> XCP on USB.\n"); printf("\n"); printf("XCP version 1.0 settings (xcp):\n"); printf(" -t1=[timeout] Command response timeout in milliseconds as a 16-bit\n"); @@ -502,6 +508,9 @@ static void DisplayProgramUsage(void) printf(" as 29-bit CAN identifiers, if this 8-bit value is > 0\n"); printf(" (Default = 0).\n"); printf("\n"); + printf("XCP on USB settings (xcp_usb):\n"); + printf(" No additional settings needed.\n"); + printf("\n"); printf("Program settings:\n"); printf(" -sm Silent mode switch. When specified, only minimal\n"); printf(" information is written to the output (Optional).\n"); @@ -594,6 +603,9 @@ static void DisplayTransportInfo(uint32_t transportType, void const * transportS case BLT_TRANSPORT_XCP_V10_CAN: printf("XCP on CAN\n"); break; + case BLT_TRANSPORT_XCP_V10_USB: + printf("XCP on USB\n"); + break; default: printf("Unknown\n"); break; @@ -671,6 +683,11 @@ static void DisplayTransportInfo(uint32_t transportType, void const * transportS } break; } + case BLT_TRANSPORT_XCP_V10_USB: + { + printf(" -> No additional settings required.\n"); + break; + } default: printf(" -> No settings specified\n"); break; @@ -956,7 +973,8 @@ static uint32_t ExtractTransportTypeFromCommandLine(int argc, char const * const } transportMap[] = { { .name = "xcp_rs232", .value = BLT_TRANSPORT_XCP_V10_RS232 }, - { .name = "xcp_can", .value = BLT_TRANSPORT_XCP_V10_CAN } + { .name = "xcp_can", .value = BLT_TRANSPORT_XCP_V10_CAN }, + { .name = "xcp_usb", .value = BLT_TRANSPORT_XCP_V10_USB } }; /* Set the default transport type in case nothing was specified on the command line. */ @@ -1158,6 +1176,12 @@ static void * ExtractTransportSettingsFromCommandLine(int argc, } } break; + /* -------------------------- XCP on USB --------------------------------------- */ + case BLT_TRANSPORT_XCP_V10_USB: + /* No additional command line parameters are neede for the USB transport + * layer. + */ + break; /* -------------------------- Unknown ------------------------------------------ */ default: /* Noting to extract. */ diff --git a/Host/Source/LibOpenBLT/CMakeLists.txt b/Host/Source/LibOpenBLT/CMakeLists.txt index 2fb0a68c..5e8e51d5 100644 --- a/Host/Source/LibOpenBLT/CMakeLists.txt +++ b/Host/Source/LibOpenBLT/CMakeLists.txt @@ -41,16 +41,16 @@ set(CMAKE_BUILD_TYPE "Debug") #**************************************************************************************** # Options #**************************************************************************************** -# Add option with default value to enable the generation and building of the static -# library. It can be overridden on the command line when CMake is called using the -# following parameter: -DBUILD_STATIC=OFF -option(BUILD_STATIC "Configurable to enable/disable building of the static library" ON) - # Add option with default value to enable the generation and building of the shared -# library. It can be overridden on the command line when CMake is called using the -# following parameter: -DBUILD_SHARED=OFF +# library. By default it is turned on. It can be overridden on the command line when +# CMake is called using the following parameter: -DBUILD_SHARED=OFF option(BUILD_SHARED "Configurable to enable/disable building of the shared library" ON) +# Add option with default value to enable the generation and building of the static +# library. By default it is turned off. It can be overridden on the command line when +# CMake is called using the following parameter: -DBUILD_STATIC=ON +option(BUILD_STATIC "Configurable to enable/disable building of the static library" OFF) + # Add option with default value to disable the generation of the PC-lint target. It can # be overridden on the command line when CMake is called using the following parameter: # -DLINT_ENABLED=ON @@ -131,6 +131,9 @@ set( #**************************************************************************************** # Only generate the static library taget if the option is enabled. Use # "make openblt_static" to individually build the static library. +# Note that when you link your own application to the static library of LibOpenBLT under +# Unix, you need to also link the LibUsb library by adding usb-1.0 to the linker library +# dependencies. if(BUILD_STATIC) add_library(openblt_static STATIC ${LIB_SRCS}) SET_TARGET_PROPERTIES(openblt_static PROPERTIES OUTPUT_NAME openblt CLEAN_DIRECT_OUTPUT 1) @@ -140,6 +143,13 @@ endif(BUILD_STATIC) # "make openblt_shared" to build individually shared library. if(BUILD_SHARED) add_library(openblt_shared SHARED ${LIB_SRCS}) + if(UNIX) + # Under Unix the LibUsb library (http://libusb.info/) is needed for the USB support. + # Make sure the libusb-1.0-0 and libusb-1.0-0-dev packages are installed to be able to + # build LibOpenBLT. Example under Debian/Ubuntu: + # sudo apt-get install libusb-1.0-0 libusb-1.0-0-dev + target_link_libraries(openblt_shared usb-1.0) + endif(UNIX) if(CMAKE_C_COMPILER_ID MATCHES MSVC) # Microsoft Visual Studio does not add "lib" to the name of the DLL, whereas GCC # (including MinGW) does. Correct this here. diff --git a/Host/Source/LibOpenBLT/lint/gnu/co-gcc.lnt b/Host/Source/LibOpenBLT/lint/gnu/co-gcc.lnt index 2132dc7b..3bc57762 100644 --- a/Host/Source/LibOpenBLT/lint/gnu/co-gcc.lnt +++ b/Host/Source/LibOpenBLT/lint/gnu/co-gcc.lnt @@ -179,6 +179,7 @@ size-options.lnt // This .lnt file should be generated (preferrably -elib(93) // allow newlines within quoted string arguments to macros -elib(46) // allow bit fields to have integral types other than // '_Bool' and 'int'. +-elibsym(793) // suppress warning about limit of 31 significant characters -elibsym(628) // Suppress 628 for __builtin symbols. -esym(528,__huge_val,__nan,__qnan,__qnanf,__snan,__snanf) diff --git a/Host/Source/LibOpenBLT/openblt.c b/Host/Source/LibOpenBLT/openblt.c index 1b7304df..f771d436 100644 --- a/Host/Source/LibOpenBLT/openblt.c +++ b/Host/Source/LibOpenBLT/openblt.c @@ -40,6 +40,7 @@ #include "xcploader.h" /* XCP loader module */ #include "xcptpuart.h" /* XCP UART transport layer */ #include "xcptpcan.h" /* XCP CAN transport layer */ +#include "xcptpusb.h" /* XCP USB transport layer */ /**************************************************************************************** @@ -49,10 +50,10 @@ * for major-, minor-, and patch-version. Version 1.05.12 would for example be * 10512. */ -#define BLT_VERSION_NUMBER (10100u) +#define BLT_VERSION_NUMBER (10200u) /** \brief The version number of the library as a null-terminated string. */ -#define BLT_VERSION_STRING "1.01.00" +#define BLT_VERSION_STRING "1.02.00" /**************************************************************************************** @@ -117,7 +118,8 @@ LIBOPENBLT_EXPORT void BltSessionInit(uint32_t sessionType, */ assert(sessionType == BLT_SESSION_XCP_V10); assert( (transportType == BLT_TRANSPORT_XCP_V10_RS232) || \ - (transportType == BLT_TRANSPORT_XCP_V10_CAN) ); + (transportType == BLT_TRANSPORT_XCP_V10_CAN) || \ + (transportType == BLT_TRANSPORT_XCP_V10_USB) ); /* Initialize the correct session. */ if (sessionType == BLT_SESSION_XCP_V10) /*lint !e774 */ @@ -169,25 +171,40 @@ LIBOPENBLT_EXPORT void BltSessionInit(uint32_t sessionType, } else if (transportType == BLT_TRANSPORT_XCP_V10_CAN) { - /* Cast transport settings to the correct type. */ - tBltTransportSettingsXcpV10Can * bltTransportSettingsXcpV10CanPtr; - bltTransportSettingsXcpV10CanPtr = - (tBltTransportSettingsXcpV10Can * )transportSettings; - /* Convert transport settings to the format supported by the XCP CAN transport - * layer. It was made static to make sure it doesn't get out of scope when - * used in xcpLoaderSettings. - */ - static tXcpTpCanSettings xcpTpCanSettings; - xcpTpCanSettings.device = bltTransportSettingsXcpV10CanPtr->deviceName; - xcpTpCanSettings.channel = bltTransportSettingsXcpV10CanPtr->deviceChannel; - xcpTpCanSettings.baudrate = bltTransportSettingsXcpV10CanPtr->baudrate; - xcpTpCanSettings.transmitId = bltTransportSettingsXcpV10CanPtr->transmitId; - xcpTpCanSettings.receiveId = bltTransportSettingsXcpV10CanPtr->receiveId; - xcpTpCanSettings.useExtended = (bltTransportSettingsXcpV10CanPtr->useExtended != 0); + /* Verify transportSettings parameters because the XCP CAN transport layer + * requires them. + */ + assert(transportSettings != NULL); + /* Only continue if the transportSettings parameter is valid. */ + if (transportSettings != NULL) /*lint !e774 */ + { + /* Cast transport settings to the correct type. */ + tBltTransportSettingsXcpV10Can * bltTransportSettingsXcpV10CanPtr; + bltTransportSettingsXcpV10CanPtr = + (tBltTransportSettingsXcpV10Can *)transportSettings; + /* Convert transport settings to the format supported by the XCP CAN transport + * layer. It was made static to make sure it doesn't get out of scope when + * used in xcpLoaderSettings. + */ + static tXcpTpCanSettings xcpTpCanSettings; + xcpTpCanSettings.device = bltTransportSettingsXcpV10CanPtr->deviceName; + xcpTpCanSettings.channel = bltTransportSettingsXcpV10CanPtr->deviceChannel; + xcpTpCanSettings.baudrate = bltTransportSettingsXcpV10CanPtr->baudrate; + xcpTpCanSettings.transmitId = bltTransportSettingsXcpV10CanPtr->transmitId; + xcpTpCanSettings.receiveId = bltTransportSettingsXcpV10CanPtr->receiveId; + xcpTpCanSettings.useExtended = (bltTransportSettingsXcpV10CanPtr->useExtended != 0); + /* Store transport layer settings in the XCP loader settings. */ + xcpLoaderSettings.transportSettings = &xcpTpCanSettings; + /* Link the transport layer to the XCP loader settings. */ + xcpLoaderSettings.transport = XcpTpCanGetTransport(); + } + } + else if (transportType == BLT_TRANSPORT_XCP_V10_USB) + { /* Store transport layer settings in the XCP loader settings. */ - xcpLoaderSettings.transportSettings = &xcpTpCanSettings; + xcpLoaderSettings.transportSettings = NULL; /* Link the transport layer to the XCP loader settings. */ - xcpLoaderSettings.transport = XcpTpCanGetTransport(); + xcpLoaderSettings.transport = XcpTpUsbGetTransport(); } /* Perform actual session initialization. */ SessionInit(XcpLoaderGetProtocol(), &xcpLoaderSettings); diff --git a/Host/Source/LibOpenBLT/openblt.h b/Host/Source/LibOpenBLT/openblt.h index f3aacada..e6010c63 100644 --- a/Host/Source/LibOpenBLT/openblt.h +++ b/Host/Source/LibOpenBLT/openblt.h @@ -103,6 +103,11 @@ LIBOPENBLT_EXPORT char const * BltVersionGetString(void); */ #define BLT_TRANSPORT_XCP_V10_CAN ((uint32_t)1u) +/** \brief Transport layer for the XCP v1.0 protocol that uses USB Bulk for data + * exchange. + */ +#define BLT_TRANSPORT_XCP_V10_USB ((uint32_t)2u) + /**************************************************************************************** * Type definitions diff --git a/Host/Source/LibOpenBLT/openblt.pas b/Host/Source/LibOpenBLT/openblt.pas index 32ec8f32..7d7bcd64 100644 --- a/Host/Source/LibOpenBLT/openblt.pas +++ b/Host/Source/LibOpenBLT/openblt.pas @@ -73,6 +73,7 @@ const // Transport layer for the XCP v1.0 protocol that uses Controller Area Network (CAN) // for data exchange. BLT_TRANSPORT_XCP_V10_CAN: LongWord = 1; + BLT_TRANSPORT_XCP_V10_USB: LongWord = 2; type // Structure layout of the XCP version 1.0 session settings. diff --git a/Host/Source/LibOpenBLT/port/linux/usbbulk.c b/Host/Source/LibOpenBLT/port/linux/usbbulk.c new file mode 100644 index 00000000..bb686184 --- /dev/null +++ b/Host/Source/LibOpenBLT/port/linux/usbbulk.c @@ -0,0 +1,366 @@ +/************************************************************************************//** +* \file port/linux/usbbulk.c +* \brief USB bulk driver source file. +* \ingroup XcpTpUsb +* \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 "usbbulk.h" /* USB bulk driver */ +#include /* LibUsb 1.0 driver */ + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +/** \brief Size of the internal endpoint read buffer. This should be the same as the size + * of the buffer size of the endpoint on the USB device itself. + */ +#define USBBULK_READ_DATA_BUFFER_SIZE (64u) + + +/**************************************************************************************** +* Local constant declarations +****************************************************************************************/ +/** \brief Vendor ID of the OpenBLT bootloader as assigned by the OpenMoko project. */ +static const uint16_t openBltVendorId = 0x1D50; + +/** \brief Product ID of the OpenBLT bootloader as assigned by the OpenMoko project. */ +static const uint16_t openBltProductId = 0x60AC; + + +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +/** \brief LibUsb context. */ +static libusb_context * libUsbCtx; + +/** \brief LibUsb device handle. */ +static libusb_device_handle * libUsbDevHandle; + +/** \brief Internal endpoint read buffer. With LibUsb endpoint read operations should + * always be attempted with the size of the endpoint buffer on the USB device + * itself. + */ +static uint8_t readDataBuffer[USBBULK_READ_DATA_BUFFER_SIZE]; + +/** \brief Variable that holds the number of bytes that were read from the endpoint, but + * were not yet retrieved from this module via UsbBulkRead(). + */ +static uint8_t readDataPending; + +/** \brief Index into the endpoint read buffer (readDataBuffer[]) that point to the next + * byte value that should be read. + */ +static uint8_t readDataCurrentReadIdx; + + +/************************************************************************************//** +** \brief Initializes the USB bulk driver. +** +****************************************************************************************/ +void UsbBulkInit(void) +{ + /* Initialize locals. */ + libUsbCtx = NULL; + libUsbDevHandle = NULL; + readDataPending = 0; + readDataCurrentReadIdx = 0; + + /* Initialize LibUsb. */ + if (libusb_init(&libUsbCtx) != (int)LIBUSB_SUCCESS) + { + /* Error occurred while initializing LibUsb. Invalidate the context. */ + libUsbCtx = NULL; + } + /* Only continue initialization with a valid context. */ + if (libUsbCtx != NULL) + { + /* Set the log message verbosity as advised by the documentation. */ + libusb_set_debug(libUsbCtx, (int)LIBUSB_LOG_LEVEL_WARNING); + } +} /*** end of UsbBulkInit ***/ + + +/************************************************************************************//** +** \brief Terminates the USB bulk driver. +** +****************************************************************************************/ +void UsbBulkTerminate(void) +{ + /* Terminate LibUsb. */ + if (libUsbCtx != NULL) + { + libusb_exit(libUsbCtx); + /* Invalidate the context. */ + libUsbCtx = NULL; + } +} /*** end of UsbBulkTerminate ***/ + + +/************************************************************************************//** +** \brief Opens the connection with the USB device. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool UsbBulkOpen(void) +{ + bool result = false; + + /* Reset read buffer management variables. */ + readDataPending = 0; + readDataCurrentReadIdx = 0; + + /* Only continue with a valid context. */ + if (libUsbCtx != NULL) + { + /* Set the result to okay and only update it in case of an error from here on. */ + result = true; + /* Attempt to open the USB device. */ + libUsbDevHandle = libusb_open_device_with_vid_pid(libUsbCtx, openBltVendorId, + openBltProductId); + /* Check if the USB device could be opened. */ + if (libUsbDevHandle == NULL) + { + /* Update result. */ + result = false; + } + /* Before the USB device can be claimed, it cannot be attached to a kernel driver. */ + if (result) + { + if (libusb_kernel_driver_active(libUsbDevHandle, 0) == 1) + { + /* Kernel driver active, so detach it. */ + (void)libusb_detach_kernel_driver(libUsbDevHandle, 0); + } + } + /* Attempt to claim the interface. */ + if (result) + { + if (libusb_claim_interface(libUsbDevHandle, 0) != (int)LIBUSB_SUCCESS) + { + result = false; + } + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of UsbBulkOpen ***/ + + +/************************************************************************************//** +** \brief Closes the connection with the USB device. +** +****************************************************************************************/ +void UsbBulkClose(void) +{ + /* Release the interface and close the connection with the USB device. */ + if (libUsbDevHandle != NULL) + { + (void)libusb_release_interface(libUsbDevHandle, 0); + libusb_close(libUsbDevHandle); + /* Invalidate the handler. */ + libUsbDevHandle = NULL; + } +} /*** end of UsbBulkClose ***/ + + +/************************************************************************************//** +** \brief Writes data to the USB device. +** \param data Pointer to byte array with data to write. +** \param length Number of bytes in the data array. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool UsbBulkWrite(uint8_t const * data, uint16_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 context and device handle. */ + if ( (libUsbDevHandle != NULL) && (libUsbCtx != NULL) ) + { + /* Attempt to write the data to the endpoint. */ + int bytesWritten = 0; + int transferResult = libusb_bulk_transfer(libUsbDevHandle, 0x01, (uint8_t *)data, + (int)length, &bytesWritten, 0); + /* Check the transfer result. */ + if (transferResult == (int)LIBUSB_SUCCESS) + { + /* Check if all data was written. */ + if (bytesWritten == length) + { + /* Data successfully written the endpoint. */ + result = true; + } + } + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of UsbBulkWrite ***/ + + +/************************************************************************************//** +** \brief Reads data from the USB device. +** \param data Pointer to byte array where received data should be stored. +** \param length Number of bytes to read from the USB device. +** \param timeout Timeout in milliseconds for the read operation. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool UsbBulkRead(uint8_t * data, uint16_t length, uint32_t timeout) +{ + bool result = false; + + /* Check parameters. */ + assert(data != NULL); + assert(length > 0); + assert(length <= USBBULK_READ_DATA_BUFFER_SIZE); + + /* Only continue with valid parameters. */ + if ((data != NULL) && (length > 0) && + (length <= USBBULK_READ_DATA_BUFFER_SIZE) ) /*lint !e774 */ + { + /* Only continue with a valid context and device handle. */ + if ( (libUsbDevHandle != NULL) && (libUsbCtx != NULL) ) + { + uint16_t totalBytesRead = 0; + uint8_t * currentWriteDataPtr = data; + + /* First empty out whatever is still pending in the read buffer. */ + uint16_t bytesPendingInBuffer = length; + if (readDataPending < length) + { + bytesPendingInBuffer = readDataPending; + } + uint16_t bytesToReadFromDevice = length - bytesPendingInBuffer; + /* Copy data. */ + for (uint16_t idx = 0; idx < bytesPendingInBuffer; idx++) + { + /* Sanity check for the current read indexer/ */ + assert(readDataCurrentReadIdx < USBBULK_READ_DATA_BUFFER_SIZE); + /* Only copy data if current read indexer is not out of bounds. */ + if (readDataCurrentReadIdx < USBBULK_READ_DATA_BUFFER_SIZE) + { + *currentWriteDataPtr = readDataBuffer[readDataCurrentReadIdx]; + } + /* Update total bytes read counter. */ + totalBytesRead++; + /* Increment the write data pointer. */ + currentWriteDataPtr++; + /* Increment current read indexer. */ + readDataCurrentReadIdx++; + /* Sanity check for data pending counter. */ + assert(readDataPending > 0); + /* Decrement data pending counter. */ + if (readDataPending > 0) + { + readDataPending--; + } + } + + /* If more data is still to be read, then perform a read operation of the full + * endpoint size. + */ + if (bytesToReadFromDevice > 0) + { + /* Sanity check. */ + assert(readDataPending == 0); + + /* Attempt to read data from the endpoint. Should be done in steps of the + * endpoint buffer size on the target. This is 64 for OpenBLT so exactly the size + * of our read buffer. + */ + int bytesRead = 0; + int transferResult = libusb_bulk_transfer(libUsbDevHandle, 0x81, readDataBuffer, + USBBULK_READ_DATA_BUFFER_SIZE, + &bytesRead, timeout); + if (transferResult == (int)LIBUSB_SUCCESS) + { + /* Update read buffer management. */ + readDataPending = (uint8_t)bytesRead; + readDataCurrentReadIdx = 0; + } + } + + /* Copy remaining data from the newly read data buffer contents as long as they + * are present. + */ + uint16_t bytesToCopy = bytesToReadFromDevice; + if (readDataPending < bytesToCopy) + { + bytesToCopy = readDataPending; + } + /* Copy data. */ + for (uint16_t idx = 0; idx < bytesToCopy; idx++) + { + /* Sanity check for the current read indexer/ */ + assert(readDataCurrentReadIdx < USBBULK_READ_DATA_BUFFER_SIZE); + /* Only copy data if current read indexer is not out of bounds. */ + if (readDataCurrentReadIdx < USBBULK_READ_DATA_BUFFER_SIZE) + { + *currentWriteDataPtr = readDataBuffer[readDataCurrentReadIdx]; + } + /* Update total bytes read counter. */ + totalBytesRead++; + /* Increment the write data pointer. */ + currentWriteDataPtr++; + /* Increment current read indexer. */ + readDataCurrentReadIdx++; + /* Sanity check for data pending counter. */ + assert(readDataPending > 0); + /* Decrement data pending counter. */ + if (readDataPending > 0) + { + readDataPending--; + } + } + + /* As a final step, check that all requested data bytes were read. */ + if (totalBytesRead == length) + { + result = true; + } + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of UsbBulkRead ***/ + + +/*********************************** end of usbbulk.c **********************************/ + diff --git a/Host/Source/LibOpenBLT/port/windows/usbbulk.c b/Host/Source/LibOpenBLT/port/windows/usbbulk.c new file mode 100644 index 00000000..e48147b5 --- /dev/null +++ b/Host/Source/LibOpenBLT/port/windows/usbbulk.c @@ -0,0 +1,374 @@ +/************************************************************************************//** +* \file port/windows/usbbulk.c +* \brief USB bulk driver source file. +* \ingroup XcpTpUsb +* \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 Windows API */ +#include "usbbulk.h" /* USB bulk driver */ + + +/**************************************************************************************** +* Macro definitions +****************************************************************************************/ +/* USB bulk driver return values. */ +#define UBL_ERROR (0u) +#define UBL_OKAY (1u) + + +/**************************************************************************************** +* Type definitions +****************************************************************************************/ +/* USB bulk driver interface functions. */ +typedef uint8_t (__stdcall * tUsbBulkLibFuncOpen)(LPGUID guid); +typedef void (__stdcall * tUsbBulkLibFuncClose)(void); +typedef uint8_t (__stdcall * tUsbBulkLibFuncTransmit)(uint8_t * data, uint16_t len); +typedef uint8_t (__stdcall * tUsbBulkLibFuncReceive)(uint8_t * data, uint16_t len, uint32_t timeout); + + +/*************************************************************************************** +* Function prototypes +****************************************************************************************/ +/* USB bulk driver handling. */ +static void UsbBulkLibLoadDll(void); +static void UsbBulkLibUnloadDll(void); +static uint8_t UsbBulkLibFuncOpen(LPGUID guid); +static void UsbBulkLibFuncClose(void); +static uint8_t UsbBulkLibFuncTransmit(uint8_t * data, uint16_t len); +static uint8_t UsbBulkLibFuncReceive(uint8_t * data, uint16_t len, uint32_t timeout); + + +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +/** \brief Handle to the USB bulk driver dynamic link library. */ +static HINSTANCE usbBulkLibDllHandle; + +/** \brief Function pointer to the USB bulk driver library Open function. */ +static tUsbBulkLibFuncOpen usbBulkLibFuncOpenPtr; + +/** \brief Function pointer to the USB bulk driver library Close function. */ +static tUsbBulkLibFuncClose usbBulkLibFuncClosePtr; + +/** \brief Function pointer to the USB bulk driver library Transmit function. */ +static tUsbBulkLibFuncTransmit usbBulkLibFuncTransmitPtr; + +/** \brief Function pointer to the USB bulk driver library Receive function. */ +static tUsbBulkLibFuncReceive usbBulkLibFuncReceivePtr; + + +/************************************************************************************//** +** \brief Initializes the USB bulk driver. +** +****************************************************************************************/ +void UsbBulkInit(void) +{ + /* Initialize locals. */ + usbBulkLibDllHandle = NULL; + /* Reset library function pointers. */ + usbBulkLibFuncOpenPtr = NULL; + usbBulkLibFuncClosePtr = NULL; + usbBulkLibFuncTransmitPtr = NULL; + usbBulkLibFuncReceivePtr = NULL; + /* Perform initialization of USB bulk driver API. */ + UsbBulkLibLoadDll(); +} /*** end of UsbBulkInit ***/ + + +/************************************************************************************//** +** \brief Terminates the USB bulk driver. +** +****************************************************************************************/ +void UsbBulkTerminate(void) +{ + /* Perform termination of USB bulk driver API. */ + UsbBulkLibUnloadDll(); +} /*** end of UsbBulkTerminate ***/ + + +/************************************************************************************//** +** \brief Opens the connection with the USB device. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool UsbBulkOpen(void) +{ + /* This must be the same GUID as the one declared in the *.inf driver file. */ + static GUID deviceGuidOpenBLT = + { + 0x807999C3, 0xE4E0, 0x40EA, 0x81, 0x88, 0x48, 0xE8, 0x52, 0xB5, 0x4F, 0x2B + }; + bool result = false; + + /* Open the connection with the USB device. */ + if (UsbBulkLibFuncOpen(&deviceGuidOpenBLT) == UBL_OKAY) + { + result = true; + } + /* Give the result back to the caller. */ + return result; +} /*** end of UsbBulkOpen ***/ + + +/************************************************************************************//** +** \brief Closes the connection with the USB device. +** +****************************************************************************************/ +void UsbBulkClose(void) +{ + /* Close the connection with the USB device. */ + UsbBulkLibFuncClose(); +} /*** end of UsbBulkClose ***/ + + +/************************************************************************************//** +** \brief Writes data to the USB device. +** \param data Pointer to byte array with data to write. +** \param length Number of bytes in the data array. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool UsbBulkWrite(uint8_t const * data, uint16_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 */ + { + /* Write data to the USB device. */ + if (UsbBulkLibFuncTransmit((uint8_t *)data, length) == UBL_OKAY) + { + result = true; + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of UsbBulkWrite ***/ + + +/************************************************************************************//** +** \brief Reads data from the USB device. +** \param data Pointer to byte array where received data should be stored. +** \param length Number of bytes to read from the USB device. +** \param timeout Timeout in milliseconds for the read operation. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool UsbBulkRead(uint8_t * data, uint16_t length, uint32_t timeout) +{ + bool result = false; + + (void)timeout; + + /* Check parameters. */ + assert(data != NULL); + assert(length > 0); + + /* Only continue with valid parameters. */ + if ((data != NULL) && (length > 0)) /*lint !e774 */ + { + /* Read data from the USB device. */ + if (UsbBulkLibFuncReceive(data, length, timeout) == UBL_OKAY) + { + result = true; + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of UsbBulkRead ***/ + + +/************************************************************************************//** +** \brief Loads the USB bulk driver DLL and initializes the API function pointers. +** +****************************************************************************************/ +static void UsbBulkLibLoadDll(void) +{ + /* Start out by resetting the API function pointers. */ + usbBulkLibFuncOpenPtr = NULL; + usbBulkLibFuncClosePtr = NULL; + usbBulkLibFuncTransmitPtr = NULL; + usbBulkLibFuncReceivePtr = NULL; + + /* Attempt to load the library and obtain a handle to it. */ + usbBulkLibDllHandle = LoadLibrary("UsbBulkLib"); + + /* Assert libary handle. */ + assert(usbBulkLibDllHandle != NULL); + + /* Only continue if the library was successfully loaded */ + if (usbBulkLibDllHandle != NULL) /*lint !e774 */ + { + /* Set UblOpen function pointer. */ + usbBulkLibFuncOpenPtr = (tUsbBulkLibFuncOpen)GetProcAddress(usbBulkLibDllHandle, "UblOpen"); + /* Set UblClose function pointer. */ + usbBulkLibFuncClosePtr = (tUsbBulkLibFuncClose)GetProcAddress(usbBulkLibDllHandle, "UblClose"); + /* Set UblTransmit function pointer. */ + usbBulkLibFuncTransmitPtr = (tUsbBulkLibFuncTransmit)GetProcAddress(usbBulkLibDllHandle, "UblTransmit"); + /* Set UblReceive function pointer. */ + usbBulkLibFuncReceivePtr = (tUsbBulkLibFuncReceive)GetProcAddress(usbBulkLibDllHandle, "UblReceive"); + } +} /*** end of UsbBulkLibLoadDll ***/ + + +/************************************************************************************//** +** \brief Unloads the USB bulk driver DLL and resets the API function pointers. +** +****************************************************************************************/ +static void UsbBulkLibUnloadDll(void) +{ + /* Reset the API function pointers. */ + usbBulkLibFuncOpenPtr = NULL; + usbBulkLibFuncClosePtr = NULL; + usbBulkLibFuncTransmitPtr = NULL; + usbBulkLibFuncReceivePtr = NULL; + + /* Unload the library and invalidate its handle. */ + if (usbBulkLibDllHandle != NULL) + { + (void)FreeLibrary(usbBulkLibDllHandle); + usbBulkLibDllHandle = NULL; + } +} /*** end of UsbBulkLibUnloadDll ***/ + + +/************************************************************************************//** +** \brief Opens and configures the connection with the USB bulk device. +** \param guid Pointer to GUID of the USB bulk device as found in the driver's +** INF-file. +** \return UBL_OKAY if successful, UBL_ERROR otherwise. +** +****************************************************************************************/ +static uint8_t UsbBulkLibFuncOpen(LPGUID guid) +{ + uint8_t result = UBL_ERROR; + + /* Check function pointer and library handle. */ + assert(usbBulkLibFuncOpenPtr != NULL); + assert(usbBulkLibDllHandle != NULL); + + /* Only continue with valid function pointer and library handle. */ + if ((usbBulkLibFuncOpenPtr != NULL) && (usbBulkLibDllHandle != NULL)) /*lint !e774 */ + { + /* Call library function. */ + result = usbBulkLibFuncOpenPtr(guid); + } + /* Give the result back to the caller. */ + return result; +} /*** end of UsbBulkLibFuncOpen ***/ + + +/************************************************************************************//** +** \brief Closes the connection with the USB bulk device and frees all the related +** handles. +** +****************************************************************************************/ +static void UsbBulkLibFuncClose(void) +{ + /* Check function pointer and library handle. */ + assert(usbBulkLibFuncClosePtr != NULL); + assert(usbBulkLibDllHandle != NULL); + + /* Only continue with valid function pointer and library handle. */ + if ((usbBulkLibFuncClosePtr != NULL) && (usbBulkLibDllHandle != NULL)) /*lint !e774 */ + { + /* Call library function. */ + usbBulkLibFuncClosePtr(); + } +} /*** end of UsbBulkLibFuncClose ***/ + + +/************************************************************************************//** +** \brief Starts transmission of the data on the bulk OUT pipe. Because USB bulk +** transmissions are quick, this function does not use the overlapped +** functionality, which means the caller is blocked until the tranmission +** completed. +** \param data Pointer to byte array with transmit data. +** \param len Number of bytes to transmit. +** \return UBL_OKAY if successful, UBL_ERROR otherwise. +** +****************************************************************************************/ +static uint8_t UsbBulkLibFuncTransmit(uint8_t * data, uint16_t len) +{ + uint8_t result = UBL_ERROR; + + /* Check function pointer and library handle. */ + assert(usbBulkLibFuncTransmitPtr != NULL); + assert(usbBulkLibDllHandle != NULL); + + /* Only continue with valid function pointer and library handle. */ + if ((usbBulkLibFuncTransmitPtr != NULL) && (usbBulkLibDllHandle != NULL)) /*lint !e774 */ + { + /* Call library function. */ + result = usbBulkLibFuncTransmitPtr(data, len); + } + /* Give the result back to the caller. */ + return result; +} /*** end of UsbBulkLibFuncTransmit ***/ + + +/************************************************************************************//** +** \brief Starts the asynchronous reception of the data from the bulk IN pipe. This +** function makes use of the overlapped functionality, which means the calling +** thread is placed into sleep mode until the reception is complete. +** \param data Pointer to byte array where the data will be stored. +** \param len Number of bytes to receive. +** \param timeout Maximum time in milliseconds for the read to complete. +** \return UBL_OKAY if successful, UBL_TIMEOUT if failure due to timeout or +** UBL_ERROR otherwise. +** +****************************************************************************************/ +static uint8_t UsbBulkLibFuncReceive(uint8_t * data, uint16_t len, uint32_t timeout) +{ + uint8_t result = UBL_ERROR; + + /* Check function pointer and library handle. */ + assert(usbBulkLibFuncReceivePtr != NULL); + assert(usbBulkLibDllHandle != NULL); + + /* Only continue with valid function pointer and library handle. */ + if ((usbBulkLibFuncReceivePtr != NULL) && (usbBulkLibDllHandle != NULL)) /*lint !e774 */ + { + /* Call library function. */ + result = usbBulkLibFuncReceivePtr(data, len, timeout); + } + /* Give the result back to the caller. */ + return result; +} /*** end of UsbBulkLibFuncReceive ***/ + + +/*********************************** end of usbbulk.c **********************************/ + diff --git a/Host/Source/LibOpenBLT/usbbulk.h b/Host/Source/LibOpenBLT/usbbulk.h new file mode 100644 index 00000000..22915fa3 --- /dev/null +++ b/Host/Source/LibOpenBLT/usbbulk.h @@ -0,0 +1,51 @@ +/************************************************************************************//** +* \file usbbulk.h +* \brief USB bulk driver header file. +* \ingroup XcpTpUsb +* \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 +****************************************************************************************/ +#ifndef USBBULK_H +#define USBBULK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +void UsbBulkInit(void); +void UsbBulkTerminate(void); +bool UsbBulkOpen(void); +void UsbBulkClose(void); +bool UsbBulkWrite(uint8_t const * data, uint16_t length); +bool UsbBulkRead(uint8_t * data, uint16_t length, uint32_t timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* USBBULK_H */ +/********************************* end of usbbulk.h ************************************/ + diff --git a/Host/Source/LibOpenBLT/xcptpusb.c b/Host/Source/LibOpenBLT/xcptpusb.c new file mode 100644 index 00000000..69b7931a --- /dev/null +++ b/Host/Source/LibOpenBLT/xcptpusb.c @@ -0,0 +1,229 @@ +/************************************************************************************//** +* \file xcptpusb.c +* \brief XCP USB transport layer source file. +* \ingroup XcpTpUsb +* \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 standard library */ +#include /* for string library */ +#include "session.h" /* Communication session module */ +#include "xcploader.h" /* XCP loader module */ +#include "xcptpusb.h" /* XCP USB transport layer */ +#include "util.h" /* Utility module */ +#include "usbbulk.h" /* USB bulk driver */ + + +/**************************************************************************************** +* Function prototypes +****************************************************************************************/ +static void XcpTpUsbInit(void const * settings); +static void XcpTpUsbTerminate(void); +static bool XcpTpUsbConnect(void); +static void XcpTpUsbDisconnect(void); +static bool XcpTpUsbSendPacket(tXcpTransportPacket const * txPacket, + tXcpTransportPacket * rxPacket, uint16_t timeout); + + +/**************************************************************************************** +* Local constant declarations +****************************************************************************************/ +/** \brief XCP transport layer structure filled with USB specifics. */ +static const tXcpTransport usbTransport = +{ + XcpTpUsbInit, + XcpTpUsbTerminate, + XcpTpUsbConnect, + XcpTpUsbDisconnect, + XcpTpUsbSendPacket +}; + + +/***********************************************************************************//** +** \brief Obtains a pointer to the transport layer structure, so that it can be +** linked to the XCP protocol module. +** \return Pointer to transport layer structure. +** +****************************************************************************************/ +tXcpTransport const * XcpTpUsbGetTransport(void) +{ + return &usbTransport; +} /*** end of XcpTpUsbGetTransport ***/ + + +/************************************************************************************//** +** \brief Initializes the transport layer. +** \param settings Pointer to settings structure. +** \return None. +** +****************************************************************************************/ +static void XcpTpUsbInit(void const * settings) +{ + /* No settings needed for this transport layer. */ + (void)settings; + + /* Initialize the USB bulk driver. */ + UsbBulkInit(); +} /*** end of XcpTpUsbInit ***/ + + +/************************************************************************************//** +** \brief Terminates the transport layer. +** +****************************************************************************************/ +static void XcpTpUsbTerminate(void) +{ + /* Terminate the USB bulk driver. */ + UsbBulkTerminate(); +} /*** end of XcpTpUsbTerminate ***/ + + +/************************************************************************************//** +** \brief Connects to the transport layer. +** \return True is connected, false otherwise. +** +****************************************************************************************/ +static bool XcpTpUsbConnect(void) +{ + bool result; + + /* Connect to USB device via USB bulk driver. */ + result = UsbBulkOpen(); + /* Give the result back to the caller. */ + return result; +} /*** end of XcpTpUsbConnect ***/ + + +/************************************************************************************//** +** \brief Disconnects from the transport layer. +** +****************************************************************************************/ +static void XcpTpUsbDisconnect(void) +{ + /* Disconnect from USB device via USB bulk driver. */ + UsbBulkClose(); +} /*** end of XcpTpUsbDisconnect ***/ + + +/************************************************************************************//** +** \brief Transmits an XCP packet on the transport layer and attempts to receive the +** response packet within the specified timeout. +** \param txPacket Pointer to the packet to transmit. +** \param rxPacket Pointer where the received packet info is stored. +** \param timeout Maximum time in milliseconds to wait for the reception of the +** response packet. +** \return True is successful and a response packet was received, false otherwise. +** +****************************************************************************************/ +static bool XcpTpUsbSendPacket(tXcpTransportPacket const * txPacket, + tXcpTransportPacket * rxPacket, uint16_t timeout) +{ + bool result = false; + uint16_t byteIdx; + /* usbBuffer is static to lower the stack load. +1 because the first byte for an XCP + * packet on the USB transport layer contains the packet lenght. + */ + static uint8_t usbBuffer[XCPLOADER_PACKET_SIZE_MAX + 1]; + uint32_t responseTimeoutTime = 0; + + /* Check parameters. */ + assert(txPacket != NULL); + assert(rxPacket != NULL); + + /* Only continue with valid parameters. */ + if ( (txPacket != NULL) && (rxPacket != NULL) ) /*lint !e774 */ + { + /* Set result value to okay and only change it from now on if an error occurred. */ + result = true; + /* Prepare the XCP packet for transmission on UART. This is basically the same as + * the XCP packet data but just the length of the packet is added to the first + * byte. + */ + usbBuffer[0] = txPacket->len; + for (byteIdx=0; byteIdxlen; byteIdx++) + { + usbBuffer[byteIdx + 1] = txPacket->data[byteIdx]; + } + /* Transmit the packet via the USB bulk driver. */ + if (!UsbBulkWrite(usbBuffer, txPacket->len + 1)) + { + result = false; + } + + /* Only continue if the transmission was successful. */ + if (result) + { + /* Determine timeout time for the response packet. */ + responseTimeoutTime = UtilTimeGetSystemTimeMs() + timeout; + /* Initialize packet reception length. */ + rxPacket->len = 0; + /* Receive the first byte. This one contains the packet length and cannot be + * zero. + */ + if (!UsbBulkRead(&rxPacket->len, 1, timeout)) + { + result = false; + } + /* Check if a valid start of packet was received, in which case the first + * byte won't have a zero value. + */ + if (rxPacket->len == 0) + { + /* No valid start of packet received, so a timeout occurred. */ + result = false; + } + } + + /* Only continue with reception if a valid packet length was received. */ + if (result) + { + /* Check if there is still time available before the initial timeout. */ + uint32_t currentTime = UtilTimeGetSystemTimeMs(); + if (currentTime >= responseTimeoutTime) + { + result = false; + } + else + { + /* Receive the actual packet data. */ + if (!UsbBulkRead(&rxPacket->data[0], rxPacket->len, responseTimeoutTime - currentTime)) + { + result = false; + } + } + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of XcpTpUsbSendPacket ***/ + + +/*********************************** end of xcptpusb.c *********************************/ diff --git a/Host/Source/LibOpenBLT/xcptpusb.h b/Host/Source/LibOpenBLT/xcptpusb.h new file mode 100644 index 00000000..d6ccd8c9 --- /dev/null +++ b/Host/Source/LibOpenBLT/xcptpusb.h @@ -0,0 +1,50 @@ +/************************************************************************************//** +* \file xcptpusb.h +* \brief XCP USB transport layer header file. +* \ingroup XcpTpUsb +* \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 +****************************************************************************************/ +/************************************************************************************//** +* \defgroup XcpTpUsb XCP USB transport layer +* \brief This module implements the XCP transport layer for USB. +* \ingroup XcpLoader +****************************************************************************************/ +#ifndef XCPTPUSB_H +#define XCPTPUSB_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************************** +* Function prototypes +****************************************************************************************/ +tXcpTransport const * XcpTpUsbGetTransport(void); + +#ifdef __cplusplus +} +#endif + +#endif /* XCPTPUSB_H */ +/*********************************** end of xcptpusb.h *********************************/ diff --git a/Host/libopenblt.dll b/Host/libopenblt.dll index 57874642..5505c3a4 100644 Binary files a/Host/libopenblt.dll and b/Host/libopenblt.dll differ diff --git a/Target/Source/boot.h b/Target/Source/boot.h index a9573967..273c6ae1 100644 --- a/Target/Source/boot.h +++ b/Target/Source/boot.h @@ -36,7 +36,7 @@ /** \brief Minor version number of the bootloader core. */ #define BOOT_VERSION_CORE_MINOR (4u) /** \brief Patch number of the bootloader core. */ -#define BOOT_VERSION_CORE_BUILD (1u) +#define BOOT_VERSION_CORE_BUILD (2u) /****************************************************************************************