diff --git a/Host/Source/LibOpenBLT/candriver.c b/Host/Source/LibOpenBLT/candriver.c index 9b570ae4..b1857c06 100644 --- a/Host/Source/LibOpenBLT/candriver.c +++ b/Host/Source/LibOpenBLT/candriver.c @@ -1,208 +1,234 @@ -/************************************************************************************//** -* \file candriver.c -* \brief Generic CAN driver source file. -* \ingroup CanDriver -* \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 "candriver.h" /* Generic CAN driver module */ - - -/**************************************************************************************** -* Local data declarations -****************************************************************************************/ -/** \brief Pointer to the CAN interface that is linked. */ -static tCanInterface const * canIfPtr; - -/** \brief Flag to store the connection status. */ -static bool canConnected; - - -/************************************************************************************//** -** \brief Initializes the CAN module. Typically called once at program startup. -** \param settings Pointer to the CAN module settings. -** \param interface Pointer to the CAN interface to link. -** -****************************************************************************************/ -void CanInit(tCanSettings const * settings, tCanInterface const * const interface) -{ - /* Initialize locals. */ - canIfPtr = NULL; - canConnected = false; - - /* Check parameters. */ - assert(settings != NULL); - assert(interface != NULL); - - /* Only continue with valid parameters. */ - if ( (settings != NULL) && (interface != NULL) ) /*lint !e774 */ - { - /* Link the CAN interface. */ - canIfPtr = interface; - /* Initialize the CAN interface. */ - canIfPtr->Init(settings); - } -} /*** end of CanInit ***/ - - -/************************************************************************************//** -** \brief Terminates the CAN module. Typically called once at program cleanup. -** -****************************************************************************************/ -void CanTerminate(void) -{ - /* Make sure a valid CAN interface is linked. */ - assert(canIfPtr != NULL); - - /* Only continue with a valid CAN interface. */ - if (canIfPtr != NULL) /*lint !e774 */ - { - /* Make sure to disconnect first. */ - CanDisconnect(); - /* Terminate the CAN interface. */ - canIfPtr->Terminate(); - /* Unlink the CAN interface. */ - canIfPtr = NULL; - } -} /*** end of CanTerminate ***/ - - -/************************************************************************************//** -** \brief Connects the CAN module. -** \return True if connected, false otherwise. -** -****************************************************************************************/ -bool CanConnect(void) -{ - bool result = false; - - /* Make sure a valid CAN interface is linked. */ - assert(canIfPtr != NULL); - - /* Only continue with a valid CAN interface. */ - if (canIfPtr != NULL) /*lint !e774 */ - { - /* Make sure that the CAN module is in the disconnected state. */ - CanDisconnect(); - /* Connect the CAN interface. */ - result = canIfPtr->Connect(); - /* Update the connection state. */ - canConnected = result; - } - /* Give the result back to the caller. */ - return result; -} /*** end of CanConnect ***/ - - -/************************************************************************************//** -** \brief Disconnects the CAN module. -** -****************************************************************************************/ -void CanDisconnect(void) -{ - /* Make sure a valid CAN interface is linked. */ - assert(canIfPtr != NULL); - - /* Only continue with a valid CAN interface. */ - if (canIfPtr != NULL) /*lint !e774 */ - { - /* Only disconnect if actually connected. */ - if (canConnected) - { - /* Disconnect CAN interface. */ - canIfPtr->Disconnect(); - /* Update the connection state. */ - canConnected = false; - } - } -} /*** end of CanDisconnect ***/ - - -/************************************************************************************//** -** \brief Obtains the connection state of the CAN module. -** \return True if connected, false otherwise. -** -****************************************************************************************/ -bool CanIsConnected(void) -{ - /* Obtain and return the connection state to the caller. */ - return canConnected; -} /*** end of CanIsConnected ***/ - - -/************************************************************************************//** -** \brief Submits a message for transmission on the CAN bus. -** \param msg Pointer to CAN message structure. -** \return True if successful, false otherwise. -** -****************************************************************************************/ -bool CanTransmit(tCanMsg const * msg) -{ - bool result = false; - - /* Make sure a valid CAN interface is linked. */ - assert(canIfPtr != NULL); - - /* Only continue with a valid CAN interface. */ - if (canIfPtr != NULL) /*lint !e774 */ - { - /* Only transmit the message if connected. */ - if (canConnected) - { - result = canIfPtr->Transmit(msg); - } - } - /* Give the result back to the caller. */ - return result; -} /*** end of CanTransmit ***/ - - -/************************************************************************************//** -** \brief Registers the event callback functions that should be called by the CAN -** module. -** \param events Pointer to structure with event callback function pointers. -** -****************************************************************************************/ -void CanRegisterEvents(tCanEvents const * events) -{ - /* Make sure a valid CAN interface is linked. */ - assert(canIfPtr != NULL); - - /* Only continue with a valid CAN interface. */ - if (canIfPtr != NULL) /*lint !e774 */ - { - /* Register the events with the CAN interface. */ - canIfPtr->RegisterEvents(events); - } -} /*** end of CanRegisterEvents ***/ - - -/*********************************** end of candriver.c ********************************/ +/************************************************************************************//** +* \file candriver.c +* \brief Generic CAN driver source file. +* \ingroup CanDriver +* \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 "candriver.h" /* Generic CAN driver module */ + + +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +/** \brief Pointer to the CAN interface that is linked. */ +static tCanInterface const * canIfPtr; + +/** \brief Flag to store the connection status. */ +static bool canConnected; + + +/************************************************************************************//** +** \brief Initializes the CAN module. Typically called once at program startup. +** \param settings Pointer to the CAN module settings. +** \param interface Pointer to the CAN interface to link. +** +****************************************************************************************/ +void CanInit(tCanSettings const * settings, tCanInterface const * const interface) +{ + /* Initialize locals. */ + canIfPtr = NULL; + canConnected = false; + + /* Check parameters. */ + assert(settings != NULL); + assert(interface != NULL); + + /* Only continue with valid parameters. */ + if ( (settings != NULL) && (interface != NULL) ) /*lint !e774 */ + { + /* Link the CAN interface. */ + canIfPtr = interface; + /* Initialize the CAN interface. */ + canIfPtr->Init(settings); + } +} /*** end of CanInit ***/ + + +/************************************************************************************//** +** \brief Terminates the CAN module. Typically called once at program cleanup. +** +****************************************************************************************/ +void CanTerminate(void) +{ + /* Make sure a valid CAN interface is linked. */ + assert(canIfPtr != NULL); + + /* Only continue with a valid CAN interface. */ + if (canIfPtr != NULL) /*lint !e774 */ + { + /* Make sure to disconnect first. */ + CanDisconnect(); + /* Terminate the CAN interface. */ + canIfPtr->Terminate(); + /* Unlink the CAN interface. */ + canIfPtr = NULL; + } +} /*** end of CanTerminate ***/ + + +/************************************************************************************//** +** \brief Connects the CAN module. +** \return True if connected, false otherwise. +** +****************************************************************************************/ +bool CanConnect(void) +{ + bool result = false; + + /* Make sure a valid CAN interface is linked. */ + assert(canIfPtr != NULL); + + /* Only continue with a valid CAN interface. */ + if (canIfPtr != NULL) /*lint !e774 */ + { + /* Make sure that the CAN module is in the disconnected state. */ + CanDisconnect(); + /* Connect the CAN interface. */ + result = canIfPtr->Connect(); + /* Update the connection state. */ + canConnected = result; + } + /* Give the result back to the caller. */ + return result; +} /*** end of CanConnect ***/ + + +/************************************************************************************//** +** \brief Disconnects the CAN module. +** +****************************************************************************************/ +void CanDisconnect(void) +{ + /* Make sure a valid CAN interface is linked. */ + assert(canIfPtr != NULL); + + /* Only continue with a valid CAN interface. */ + if (canIfPtr != NULL) /*lint !e774 */ + { + /* Only disconnect if actually connected. */ + if (canConnected) + { + /* Disconnect CAN interface. */ + canIfPtr->Disconnect(); + /* Update the connection state. */ + canConnected = false; + } + } +} /*** end of CanDisconnect ***/ + + +/************************************************************************************//** +** \brief Obtains the connection state of the CAN module. +** \return True if connected, false otherwise. +** +****************************************************************************************/ +bool CanIsConnected(void) +{ + /* Obtain and return the connection state to the caller. */ + return canConnected; +} /*** end of CanIsConnected ***/ + + +/************************************************************************************//** +** \brief Submits a message for transmission on the CAN bus. +** \param msg Pointer to CAN message structure. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +bool CanTransmit(tCanMsg const * msg) +{ + bool result = false; + + /* Make sure a valid CAN interface is linked. */ + assert(canIfPtr != NULL); + + /* Only continue with a valid CAN interface. */ + if (canIfPtr != NULL) /*lint !e774 */ + { + /* Only transmit the message if connected. */ + if (canConnected) + { + result = canIfPtr->Transmit(msg); + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of CanTransmit ***/ + + +/************************************************************************************//** +** \brief Checks if a bus off or bus heavy situation occurred. +** \return True if a bus error situation was detected, false otherwise. +** +****************************************************************************************/ +bool CanIsBusError(void) +{ + bool result = false; + + /* Make sure a valid CAN interface is linked. */ + assert(canIfPtr != NULL); + + /* Only continue with a valid CAN interface. */ + if (canIfPtr != NULL) /*lint !e774 */ + { + /* Only check for bus error if connected. */ + if (canConnected) + { + result = canIfPtr->IsBusError(); + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of CanIsBusError ***/ + + +/************************************************************************************//** +** \brief Registers the event callback functions that should be called by the CAN +** module. +** \param events Pointer to structure with event callback function pointers. +** +****************************************************************************************/ +void CanRegisterEvents(tCanEvents const * events) +{ + /* Make sure a valid CAN interface is linked. */ + assert(canIfPtr != NULL); + + /* Only continue with a valid CAN interface. */ + if (canIfPtr != NULL) /*lint !e774 */ + { + /* Register the events with the CAN interface. */ + canIfPtr->RegisterEvents(events); + } +} /*** end of CanRegisterEvents ***/ + + +/*********************************** end of candriver.c ********************************/ diff --git a/Host/Source/LibOpenBLT/candriver.h b/Host/Source/LibOpenBLT/candriver.h index 21d2f69a..88b527c2 100644 --- a/Host/Source/LibOpenBLT/candriver.h +++ b/Host/Source/LibOpenBLT/candriver.h @@ -90,13 +90,13 @@ typedef struct t_can_msg * .mask = 0x00000000 * Example 2: Receive only CAN identifier 0x124 (11-bit or 29-bit) * .code = 0x00000124 - * .mask = 0x00000124 + * .mask = 0x1fffffff * Example 3: Receive only CAN identifier 0x124 (11-bit) * .code = 0x00000124 - * .mask = 0x80000124 + * .mask = 0x9fffffff * Example 4: Receive only CAN identifier 0x124 (29-bit) * .code = 0x80000124 - * .mask = 0x80000124 + * .mask = 0x9fffffff */ typedef struct t_can_settings { @@ -129,6 +129,8 @@ typedef struct t_can_interface void (*Disconnect) (void); /** \brief Submits a CAN message for transmission. */ bool (*Transmit) (tCanMsg const * msg); + /** \brief Check if a bus off and/or bus heavy situation occurred. */ + bool (*IsBusError) (void); /** \brief Registers the event callback functions. */ void (*RegisterEvents) (tCanEvents const * events); } tCanInterface; @@ -143,6 +145,7 @@ bool CanConnect(void); void CanDisconnect(void); bool CanIsConnected(void); bool CanTransmit(tCanMsg const * msg); +bool CanIsBusError(void); void CanRegisterEvents(tCanEvents const * events); #ifdef __cplusplus diff --git a/Host/Source/LibOpenBLT/port/windows/canif/peak/pcanusb.c b/Host/Source/LibOpenBLT/port/windows/canif/peak/pcanusb.c index baba99ee..a41acce4 100644 --- a/Host/Source/LibOpenBLT/port/windows/canif/peak/pcanusb.c +++ b/Host/Source/LibOpenBLT/port/windows/canif/peak/pcanusb.c @@ -33,51 +33,140 @@ #include /* for standard integer types */ #include /* for NULL declaration */ #include /* for boolean type */ -#include /* for standard library */ -#include /* for string library */ +#include /* for standard library */ +#include /* for string library */ #include "candriver.h" /* Generic CAN driver module */ #include "pcanusb.h" /* Peak PCAN-USB interface */ #include /* for Windows API */ #include "PCANBasic.h" /* for PCAN-Basic API */ -/*************************************************************************************** -* Function prototypes -****************************************************************************************/ -static void PCanUsbInit(tCanSettings const * settings); -static void PCanUsbTerminate(void); -static bool PCanUsbConnect(void); -static void PCanUsbDisconnect(void); -static bool PCanUsbTransmit(tCanMsg const * msg); -static void PCanUsbRegisterEvents(tCanEvents const * events); +/*************************************************************************************** +* Type definitions +****************************************************************************************/ +/* Type definitions of the function in the PCAN-Basic API that this CAN interface uses.*/ +typedef TPCANStatus (__stdcall * tPCanUsbLibFuncInitialize)(TPCANHandle, TPCANBaudrate, TPCANType, DWORD, WORD); +typedef TPCANStatus (__stdcall * tPCanUsbLibFuncpUninitialize)(TPCANHandle); +typedef TPCANStatus (__stdcall * tPCanUsbLibFuncGetStatus)(TPCANHandle); +typedef TPCANStatus (__stdcall * tPCanUsbLibFuncSetValue)(TPCANHandle, TPCANParameter, void*, DWORD); +typedef TPCANStatus (__stdcall * tPCanUsbLibFuncRead)(TPCANHandle, TPCANMsg*, TPCANTimestamp*); +typedef TPCANStatus (__stdcall * tPCanUsbLibFuncWrite)(TPCANHandle, TPCANMsg*); +typedef TPCANStatus (__stdcall * tPCanUsbLibFuncFilterMessages)(TPCANHandle, DWORD, DWORD, TPCANMode); - -/**************************************************************************************** -* Local constant declarations -****************************************************************************************/ -/** \brief CAN interface structure filled with Peak PCAN-USB specifics. */ -static const tCanInterface pCanUsbInterface = -{ - PCanUsbInit, - PCanUsbTerminate, - PCanUsbConnect, - PCanUsbDisconnect, - PCanUsbTransmit, - PCanUsbRegisterEvents -}; - -/**************************************************************************************** -* Local data declarations -****************************************************************************************/ -/** \brief The settings to use in this CAN interface. */ -static tCanSettings pCanUsbSettings; - -/** \brief List with callback functions that this driver should use. */ -static tCanEvents * pCanUsbEventsList; - -/** \brief Total number of event entries into the \ref pCanUsbEventsList list. */ -static uint32_t pCanUsbEventsEntries; +/*************************************************************************************** +* Function prototypes +****************************************************************************************/ +/* CAN interface functions. */ +static void PCanUsbInit(tCanSettings const * settings); +static void PCanUsbTerminate(void); +static bool PCanUsbConnect(void); +static void PCanUsbDisconnect(void); +static bool PCanUsbTransmit(tCanMsg const * msg); +static bool PCanUsbIsBusError(void); +static void PCanUsbRegisterEvents(tCanEvents const * events); +/* CAN message reception thread. */ +static DWORD WINAPI PCanUsbReceptionThread(LPVOID pv); +/* PCAN-Basic library handling. */ +static void PCanUsbLibLoadDll(void); +static void PCanUsbLibUnloadDll(void); +static TPCANStatus PCanUsbLibFuncInitialize(TPCANHandle Channel, TPCANBaudrate Btr0Btr1, + TPCANType HwType, DWORD IOPort, + WORD Interrupt); +static TPCANStatus PCanUsbLibFuncpUninitialize(TPCANHandle Channel); +static TPCANStatus PCanUsbLibFuncGetStatus(TPCANHandle Channel); +static TPCANStatus PCanUsbLibFuncSetValue(TPCANHandle Channel, TPCANParameter Parameter, + void * Buffer, DWORD BufferLength); +static TPCANStatus PCanUsbLibFuncRead(TPCANHandle Channel, TPCANMsg * MessageBuffer, + TPCANTimestamp * TimestampBuffer); +static TPCANStatus PCanUsbLibFuncWrite(TPCANHandle Channel, TPCANMsg * MessageBuffer); +static TPCANStatus PCanUsbLibFuncFilterMessages(TPCANHandle Channel, DWORD FromID, + DWORD ToID, TPCANMode Mode); + + +/**************************************************************************************** +* Local constant declarations +****************************************************************************************/ +/** \brief CAN interface structure filled with Peak PCAN-USB specifics. */ +static const tCanInterface pCanUsbInterface = +{ + PCanUsbInit, + PCanUsbTerminate, + PCanUsbConnect, + PCanUsbDisconnect, + PCanUsbTransmit, + PCanUsbIsBusError, + PCanUsbRegisterEvents +}; + +/** \brief PCAN-USB channel handle lookup table. The pCanUsbSettings.channel value can + * be used as the index. + */ +static const TPCANHandle pCanUsbChannelLookup[] = +{ + PCAN_USBBUS1, /* PCAN-USB interface, channel 1. */ + PCAN_USBBUS2, /* PCAN-USB interface, channel 2. */ + PCAN_USBBUS3, /* PCAN-USB interface, channel 3. */ + PCAN_USBBUS4, /* PCAN-USB interface, channel 4. */ + PCAN_USBBUS5, /* PCAN-USB interface, channel 5. */ + PCAN_USBBUS6, /* PCAN-USB interface, channel 6. */ + PCAN_USBBUS7, /* PCAN-USB interface, channel 7. */ + PCAN_USBBUS8, /* PCAN-USB interface, channel 8. */ + PCAN_USBBUS9, /* PCAN-USB interface, channel 9. */ + PCAN_USBBUS10, /* PCAN-USB interface, channel 10. */ + PCAN_USBBUS11, /* PCAN-USB interface, channel 11. */ + PCAN_USBBUS12, /* PCAN-USB interface, channel 12. */ + PCAN_USBBUS13, /* PCAN-USB interface, channel 13. */ + PCAN_USBBUS14, /* PCAN-USB interface, channel 14. */ + PCAN_USBBUS15, /* PCAN-USB interface, channel 15. */ + PCAN_USBBUS16 /* PCAN-USB interface, channel 16. */ +}; + + +/**************************************************************************************** +* Local data declarations +****************************************************************************************/ +/** \brief The settings to use in this CAN interface. */ +static tCanSettings pCanUsbSettings; + +/** \brief List with callback functions that this driver should use. */ +static tCanEvents * pCanUsbEventsList; + +/** \brief Total number of event entries into the \ref pCanUsbEventsList list. */ +static uint32_t pCanUsbEventsEntries; + +/** \brief Handle to the PCAN-Basic dynamic link library. */ +static HINSTANCE pCanUsbDllHandle; + +/** \brief Function pointer to the PCAN-Basic Initialize function. */ +static tPCanUsbLibFuncInitialize pCanUsbLibFuncInitializePtr; + +/** \brief Function pointer to the PCAN-Basic Uninitialize function. */ +static tPCanUsbLibFuncpUninitialize pCanUsbLibFuncpUninitializePtr; + +/** \brief Function pointer to the PCAN-Basic GetStatus function. */ +static tPCanUsbLibFuncGetStatus pCanUsbLibFuncGetStatusPtr; + +/** \brief Function pointer to the PCAN-Basic SetValue function. */ +static tPCanUsbLibFuncSetValue pCanUsbLibFuncSetValuePtr; + +/** \brief Function pointer to the PCAN-Basic Read function. */ +static tPCanUsbLibFuncRead pCanUsbLibFuncReadPtr; + +/** \brief Function pointer to the PCAN-Basic Write function. */ +static tPCanUsbLibFuncWrite pCanUsbLibFuncWritePtr; + +/** \brief Function pointer to the PCAN-Basic FilterMessages function. */ +static tPCanUsbLibFuncFilterMessages pCanUsbLibFuncFilterMessagesPtr; + +/** \brief Handle for the event to terminate the reception thread. */ +static HANDLE pCanUsbTerminateEvent; + +/** \brief Handle for a CAN related event. */ +static HANDLE pCanUsbCanEvent; + +/** \brief Handle for the CAN reception thread. */ +static HANDLE pCanUsbRxThreadHandle; /***********************************************************************************//** @@ -92,172 +181,817 @@ tCanInterface const * PCanUsbGetInterface(void) } /*** end of PCanUsbGetInterface ***/ -/************************************************************************************//** -** \brief Initializes the CAN interface. -** \param settings Pointer to the CAN interface settings. -** -****************************************************************************************/ -static void PCanUsbInit(tCanSettings const * settings) -{ - char * canDeviceName; - - /* Initialize locals. */ - pCanUsbEventsList = NULL; - pCanUsbEventsEntries = 0; - /* Reset CAN interface settings. */ - pCanUsbSettings.devicename = ""; - pCanUsbSettings.channel = 0; - pCanUsbSettings.baudrate = CAN_BR500K; - pCanUsbSettings.code = 0x00000000u; - pCanUsbSettings.mask = 0x00000000u; - - /* Check parameters. */ - assert(settings != NULL); - - /* Only continue with valid parameters. */ - if (settings != NULL) /*lint !e774 */ - { - /* Shallow copy the CAN interface settings for later usage. */ - pCanUsbSettings = *settings; - /* The devicename is a pointer and it is not gauranteed that it stays valid so we need - * to deep copy this one. note the +1 for '\0' in malloc. - */ - assert(settings->devicename != NULL); - if (settings->devicename != NULL) /*lint !e774 */ - { - canDeviceName = malloc(strlen(settings->devicename) + 1); - assert(canDeviceName != NULL); - if (canDeviceName != NULL) /*lint !e774 */ - { - strcpy(canDeviceName, settings->devicename); - pCanUsbSettings.devicename = canDeviceName; - } - } - } - /* ##Vg TODO Perform initialization of PCAN-Basic API. */ -} /*** end of PCanUsbInit ***/ - - -/************************************************************************************//** -** \brief Terminates the CAN interface. -** -****************************************************************************************/ -static void PCanUsbTerminate(void) -{ - /* ##Vg TODO Perform termination of PCAN-Basic API. */ - /* Release memory that was allocated for storing the device name. */ - if (pCanUsbSettings.devicename != NULL) - { - free((char *)pCanUsbSettings.devicename); - } - /* Reset CAN interface settings. */ - pCanUsbSettings.devicename = ""; - pCanUsbSettings.channel = 0; - pCanUsbSettings.baudrate = CAN_BR500K; - pCanUsbSettings.code = 0x00000000u; - pCanUsbSettings.mask = 0x00000000u; - /* Release memory that was allocated for CAN events and reset the entry count. */ - if ( (pCanUsbEventsList != NULL) && (pCanUsbEventsEntries != 0) ) - { - free(pCanUsbEventsList); - pCanUsbEventsEntries = 0; - } -} /*** end of PCanUsbTerminate ***/ - - -/************************************************************************************//** -** \brief Connects the CAN interface. -** \return True if connected, false otherwise. -** -****************************************************************************************/ -static bool PCanUsbConnect(void) -{ - bool result = false; - - /* ##Vg TODO Check CAN interface settings. */ - - /* ##Vg TODO Connect to CAN interface, if settings are valid. */ - - /* Give the result back to the caller. */ - return result; -} /*** end of PCanUsbConnect ***/ - - -/************************************************************************************//** -** \brief Disconnects the CAN interface. -** -****************************************************************************************/ -static void PCanUsbDisconnect(void) -{ - /* ##Vg TODO Disconnect from the CAN interface. */ -} /*** end of PCanUsbDisconnect ***/ - - -/************************************************************************************//** -** \brief Submits a message for transmission on the CAN bus. -** \param msg Pointer to CAN message structure. -** \return True if successful, false otherwise. -** -****************************************************************************************/ -static bool PCanUsbTransmit(tCanMsg const * msg) -{ - bool result = false; - - /* Check parameters. */ - assert(msg != NULL); - - /* Only continue with valid parameters. */ - if (msg != NULL) /*lint !e774 */ - { - /* ##Vg TODO Submit CAN message for transmission */ - } - - /* Give the result back to the caller. */ - return result; -} /*** end of PCanUsbTransmit ***/ - - -/************************************************************************************//** -** \brief Registers the event callback functions that should be called by the CAN -** interface. -** \param events Pointer to structure with event callback function pointers. -** -****************************************************************************************/ -static void PCanUsbRegisterEvents(tCanEvents const * events) -{ - /* Check parameters. */ - assert(events != NULL); - - /* ##Vg TODO Test with multiple event entries to check that realloc approach works. */ - - /* Only continue with valid parameters. */ - if (events != NULL) /*lint !e774 */ - { - /* Increase length of the list to make space for one more event entry. Note that - * it is okay to call realloc with a NULL pointer. In this case it simply behaves - * as malloc. - */ - pCanUsbEventsList = realloc(pCanUsbEventsList, - (sizeof(tCanEvents) * (pCanUsbEventsEntries + 1))); - /* Assert reallocation. */ - assert(pCanUsbEventsList != NULL); - /* Only continue if reallocation was successful. */ - if (pCanUsbEventsList != NULL) - { - /* Increment events entry count. */ - pCanUsbEventsEntries++; - /* Store the events in the new entry. */ - pCanUsbEventsList[pCanUsbEventsEntries - 1] = *events; - } - /* Reallocation failed. */ - else - { - /* Reset events entry count. */ - pCanUsbEventsEntries = 0; - } - } -} /*** end of PCanUsbRegisterEvents ***/ - - +/************************************************************************************//** +** \brief Initializes the CAN interface. +** \param settings Pointer to the CAN interface settings. +** +****************************************************************************************/ +static void PCanUsbInit(tCanSettings const * settings) +{ + char * canDeviceName; + + /* Initialize locals. */ + pCanUsbEventsList = NULL; + pCanUsbEventsEntries = 0; + pCanUsbTerminateEvent = NULL; + pCanUsbCanEvent = NULL; + pCanUsbRxThreadHandle = NULL; + pCanUsbDllHandle = NULL; + /* Reset library function pointers. */ + pCanUsbLibFuncInitializePtr = NULL; + pCanUsbLibFuncpUninitializePtr = NULL; + pCanUsbLibFuncGetStatusPtr = NULL; + pCanUsbLibFuncSetValuePtr = NULL; + pCanUsbLibFuncReadPtr = NULL; + pCanUsbLibFuncWritePtr = NULL; + pCanUsbLibFuncFilterMessagesPtr = NULL; + /* Reset CAN interface settings. */ + pCanUsbSettings.devicename = ""; + pCanUsbSettings.channel = 0; + pCanUsbSettings.baudrate = CAN_BR500K; + pCanUsbSettings.code = 0x00000000u; + pCanUsbSettings.mask = 0x00000000u; + + /* Check parameters. */ + assert(settings != NULL); + + /* Only continue with valid parameters. */ + if (settings != NULL) /*lint !e774 */ + { + /* Shallow copy the CAN interface settings for later usage. */ + pCanUsbSettings = *settings; + /* The devicename is a pointer and it is not gauranteed that it stays valid so we need + * to deep copy this one. note the +1 for '\0' in malloc. + */ + assert(settings->devicename != NULL); + if (settings->devicename != NULL) /*lint !e774 */ + { + canDeviceName = malloc(strlen(settings->devicename) + 1); + assert(canDeviceName != NULL); + if (canDeviceName != NULL) /*lint !e774 */ + { + strcpy(canDeviceName, settings->devicename); + pCanUsbSettings.devicename = canDeviceName; + } + } + /* Perform initialization of PCAN-Basic API. */ + PCanUsbLibLoadDll(); + } +} /*** end of PCanUsbInit ***/ + + +/************************************************************************************//** +** \brief Terminates the CAN interface. +** +****************************************************************************************/ +static void PCanUsbTerminate(void) +{ + /* Perform termination of PCAN-Basic API. */ + PCanUsbLibUnloadDll(); + /* Release memory that was allocated for storing the device name. */ + if (pCanUsbSettings.devicename != NULL) + { + free((char *)pCanUsbSettings.devicename); + } + /* Reset CAN interface settings. */ + pCanUsbSettings.devicename = ""; + pCanUsbSettings.channel = 0; + pCanUsbSettings.baudrate = CAN_BR500K; + pCanUsbSettings.code = 0x00000000u; + pCanUsbSettings.mask = 0x00000000u; + /* Release memory that was allocated for CAN events and reset the entry count. */ + if ( (pCanUsbEventsList != NULL) && (pCanUsbEventsEntries != 0) ) + { + free(pCanUsbEventsList); + pCanUsbEventsEntries = 0; + } +} /*** end of PCanUsbTerminate ***/ + + +/************************************************************************************//** +** \brief Connects the CAN interface. +** \return True if connected, false otherwise. +** +****************************************************************************************/ +static bool PCanUsbConnect(void) +{ + bool result = false; + bool baudrateSupported = true; + bool channelSupported; + bool libInitialized = false; + TPCANBaudrate baudrate = PCAN_BAUD_500K; + uint32_t iBuffer; + + /* Convert the baudrate to a value supported by the PCAN-Basic API. */ + switch (pCanUsbSettings.baudrate) + { + case CAN_BR10K: + baudrate = PCAN_BAUD_10K; + break; + case CAN_BR20K: + baudrate = PCAN_BAUD_20K; + break; + case CAN_BR50K: + baudrate = PCAN_BAUD_50K; + break; + case CAN_BR100K: + baudrate = PCAN_BAUD_100K; + break; + case CAN_BR125K: + baudrate = PCAN_BAUD_125K; + break; + case CAN_BR250K: + baudrate = PCAN_BAUD_250K; + break; + case CAN_BR500K: + baudrate = PCAN_BAUD_500K; + break; + case CAN_BR800K: + baudrate = PCAN_BAUD_800K; + break; + case CAN_BR1M: + baudrate = PCAN_BAUD_1M; + break; + default: + baudrateSupported = false; + break; + } + + /* Validate channel index. For this CAN interface, the channel index specifies the + * PCAN-USB device, in case multiple are connected. + */ + channelSupported = (pCanUsbSettings.channel < (sizeof(pCanUsbChannelLookup) / + sizeof(pCanUsbChannelLookup[0]))); + + /* Note that the device name itself is not needed anymore at this point, it was only + * needed by the CAN driver to link the correct interface (this one). Check settings. + */ + assert(baudrateSupported); + assert(channelSupported); + + /* Only continue with valid settings. */ + if ( (baudrateSupported) && (channelSupported) ) + { + /* Init result code to success and only negate it on detection of error. */ + result = true; + /* Connect to the CAN hardware interface. */ + if (PCanUsbLibFuncInitialize(pCanUsbChannelLookup[pCanUsbSettings.channel], + baudrate, 0, 0, 0) != PCAN_ERROR_OK) + { + result = false; + } + else + { + libInitialized = true; + } + + /* Create the terminate event handle used in the reception thread. */ + if (result) + { + pCanUsbTerminateEvent = CreateEvent(NULL, TRUE, FALSE, ""); + if (pCanUsbTerminateEvent == NULL) + { + result = false; + } + } + + /* Create the CAN event handle used in the reception thread. */ + if (result) + { + pCanUsbCanEvent = CreateEvent(NULL, FALSE, FALSE, ""); + if (pCanUsbCanEvent == NULL) + { + result = false; + } + } + + /* Enable the bus off auto reset. */ + if (result) + { + iBuffer = PCAN_PARAMETER_ON; + if (PCanUsbLibFuncSetValue(pCanUsbChannelLookup[pCanUsbSettings.channel], + PCAN_BUSOFF_AUTORESET, &iBuffer, + sizeof(iBuffer)) != PCAN_ERROR_OK) + { + result = false; + } + } + + /* Configure reception acceptance filter, if it is not supposed to be fully open. */ + if ( (result) && (pCanUsbSettings.mask != 0x00000000u) ) + { + /* Configuration of the reception acceptance filter in the PCAN-Basic library does + * not use a mask and code approach. Instead it has an API function for setting + * the filter by specifing an identifier range. This means the mask and code pair + * should be used to calculate the lowest and highest identifier that should pass + * the filter. It is not 100% accurate. In some cases more identifiers can pass + * the filter than desired, but there is no other option: + * Lowest CAN ID = (code & mask) & 0x1fffffff + * Highest CAN ID = (code | ~mask) & 0x1fffffff + */ + uint32_t lowestCanID = (pCanUsbSettings.code & pCanUsbSettings.mask) & 0x1fffffffu; + uint32_t highestCanID = (pCanUsbSettings.code | ~pCanUsbSettings.mask) & 0x1fffffffu; + /* Use bit logic to determine if the filter should accept standard 11-bit and/or + * extended 29-bit identifiers: + * acceptStdId = ((mask & code & CAN_MSG_EXT_ID_MASK) == 0) + * acceptExtId = ((mask & code & CAN_MSG_EXT_ID_MASK) != 0) || + * ((mask & CAN_MSG_EXT_ID_MASK) == 0) + */ + bool acceptStdID = ((pCanUsbSettings.mask & pCanUsbSettings.code & CAN_MSG_EXT_ID_MASK) == 0); + bool acceptExtID = ((pCanUsbSettings.mask & pCanUsbSettings.code & CAN_MSG_EXT_ID_MASK) != 0) || + ((pCanUsbSettings.mask & CAN_MSG_EXT_ID_MASK) == 0); + /* Configure acceptance filter for standard 11-bit identifiers. */ + if (acceptStdID) + { + if (PCanUsbLibFuncFilterMessages(pCanUsbChannelLookup[pCanUsbSettings.channel], + lowestCanID, highestCanID, + PCAN_MODE_STANDARD) != PCAN_ERROR_OK) + { + result = false; + } + } + /* Configure acceptance filter for extended 29-bit identifiers. */ + if ( (acceptExtID) && (result) ) + { + if (PCanUsbLibFuncFilterMessages(pCanUsbChannelLookup[pCanUsbSettings.channel], + lowestCanID, highestCanID, + PCAN_MODE_EXTENDED) != PCAN_ERROR_OK) + { + result = false; + } + } + } + + /* Register the event reception handle. */ + if (result) + { + if (PCanUsbLibFuncSetValue(pCanUsbChannelLookup[pCanUsbSettings.channel], + PCAN_RECEIVE_EVENT, &pCanUsbCanEvent, + sizeof(pCanUsbCanEvent)) != PCAN_ERROR_OK) + { + result = false; + } + } + + /* Start the reception thread as the last step. */ + if (result) + { + pCanUsbRxThreadHandle = CreateThread(NULL, 0, PCanUsbReceptionThread, + NULL, 0, NULL); + if (pCanUsbRxThreadHandle == NULL) + { + result = false; + } + } + } + + /* Clean-up in case an error occurred. */ + if (!result) + { + if (libInitialized) + { + /* Uninitialize the library. */ + (void)PCanUsbLibFuncpUninitialize(pCanUsbChannelLookup[pCanUsbSettings.channel]); + } + if (pCanUsbTerminateEvent != NULL) + { + /* Close the event handle. */ + (void)CloseHandle(pCanUsbTerminateEvent); + pCanUsbTerminateEvent = NULL; + } + if (pCanUsbCanEvent != NULL) + { + /* Close the event handle. */ + (void)CloseHandle(pCanUsbCanEvent); + pCanUsbCanEvent = NULL; + } + } + + /* Give the result back to the caller. */ + return result; +} /*** end of PCanUsbConnect ***/ + + +/************************************************************************************//** +** \brief Disconnects the CAN interface. +** +****************************************************************************************/ +static void PCanUsbDisconnect(void) +{ + /* Stop the reception thread. */ + if (pCanUsbRxThreadHandle != NULL) + { + /* Trigger event to request the reception thread to stop. */ + (void)SetEvent(pCanUsbTerminateEvent); + /* Wait for the thread to signal termination. */ + (void)WaitForSingleObject(pCanUsbRxThreadHandle, INFINITE); + /* Close the thread handle. */ + (void)CloseHandle(pCanUsbRxThreadHandle); + } + + /* Close the terminate event handle. */ + if (pCanUsbTerminateEvent != NULL) + { + (void)CloseHandle(pCanUsbTerminateEvent); + pCanUsbTerminateEvent = NULL; + } + /* Close the CAN event handle. */ + if (pCanUsbCanEvent != NULL) + { + (void)CloseHandle(pCanUsbCanEvent); + pCanUsbCanEvent = NULL; + } + /* Disconnect from the CAN interface. */ + (void)PCanUsbLibFuncpUninitialize(pCanUsbChannelLookup[pCanUsbSettings.channel]); +} /*** end of PCanUsbDisconnect ***/ + + +/************************************************************************************//** +** \brief Submits a message for transmission on the CAN bus. +** \param msg Pointer to CAN message structure. +** \return True if successful, false otherwise. +** +****************************************************************************************/ +static bool PCanUsbTransmit(tCanMsg const * msg) +{ + bool result = false; + TPCANMsg msgBuf; + tCanEvents const * pEvents; + + /* Check parameters. */ + assert(msg != NULL); + + /* Only continue with valid parameters. */ + if (msg != NULL) /*lint !e774 */ + { + /* Convert the message to a type supported by the PCAN-Basic API. */ + if ((msg->id & CAN_MSG_EXT_ID_MASK) == 0) + { + msgBuf.ID = msg->id & 0x7ffu; + msgBuf.MSGTYPE = PCAN_MESSAGE_STANDARD; + } + else + { + msgBuf.ID = msg->id & 0x1fffffffu; + msgBuf.MSGTYPE = PCAN_MESSAGE_EXTENDED; + } + msgBuf.LEN = msg->dlc; + for (uint8_t idx = 0; idx < msgBuf.LEN; idx++) + { + msgBuf.DATA[idx] = msg->data[idx]; + } + + /* Submit CAN message for transmission. */ + if (PCanUsbLibFuncWrite(pCanUsbChannelLookup[pCanUsbSettings.channel], + &msgBuf) == PCAN_ERROR_OK) + { + /* Update result value to success. */ + result = true; + /* Trigger transmit complete event(s). */ + pEvents = pCanUsbEventsList; + for (uint32_t idx = 0; idx < pCanUsbEventsEntries; idx++) + { + if (pEvents != NULL) + { + if (pEvents->MsgTxed != NULL) + { + pEvents->MsgTxed(msg); + } + /* Move on to the next entry in the list. */ + pEvents++; + } + } + } + } + /* Give the result back to the caller. */ + return result; +} /*** end of PCanUsbTransmit ***/ + + +/************************************************************************************//** +** \brief Checks if a bus off or bus heavy situation occurred. +** \return True if a bus error situation was detected, false otherwise. +** +****************************************************************************************/ +static bool PCanUsbIsBusError(void) +{ + bool result = false; + TPCANStatus status; + + /* Obtain the status information. */ + status = PCanUsbLibFuncGetStatus(pCanUsbChannelLookup[pCanUsbSettings.channel]); + + /* Process the status to detect bus off or bus heavy. */ + if ((status == PCAN_ERROR_BUSOFF) || (status == PCAN_ERROR_BUSHEAVY)) + { + result = true; + } + /* Give the result back to the caller. */ + return result; +} /*** end of PCanUsbIsBusError ***/ + + +/************************************************************************************//** +** \brief Registers the event callback functions that should be called by the CAN +** interface. +** \param events Pointer to structure with event callback function pointers. +** +****************************************************************************************/ +static void PCanUsbRegisterEvents(tCanEvents const * events) +{ + /* Check parameters. */ + assert(events != NULL); + + /* Only continue with valid parameters. */ + if (events != NULL) /*lint !e774 */ + { + /* Increase length of the list to make space for one more event entry. Note that + * it is okay to call realloc with a NULL pointer. In this case it simply behaves + * as malloc. + */ + pCanUsbEventsList = realloc(pCanUsbEventsList, + (sizeof(tCanEvents) * (pCanUsbEventsEntries + 1))); + /* Assert reallocation. */ + assert(pCanUsbEventsList != NULL); + /* Only continue if reallocation was successful. */ + if (pCanUsbEventsList != NULL) + { + /* Increment events entry count. */ + pCanUsbEventsEntries++; + /* Store the events in the new entry. */ + pCanUsbEventsList[pCanUsbEventsEntries - 1] = *events; + } + /* Reallocation failed. */ + else + { + /* Reset events entry count. */ + pCanUsbEventsEntries = 0; + } + } +} /*** end of PCanUsbRegisterEvents ***/ + + +/************************************************************************************//** +** \brief CAN message reception thread. +** \param pv Pointer to thread parameters. +** \return Thread exit code. +** +****************************************************************************************/ +static DWORD WINAPI PCanUsbReceptionThread(LPVOID pv) +{ + DWORD waitResult; + HANDLE handles[] = + { + pCanUsbCanEvent, + pCanUsbTerminateEvent + }; + bool running = true; + TPCANMsg rxLibMsg; + tCanMsg rxMsg; + tCanEvents const * pEvents; + + /* Parameter not used. */ + (void)pv; + + /* Enter thread's infinite loop. */ + while (running) + { + waitResult = WaitForMultipleObjects(sizeof(handles)/sizeof(handles[0]), handles, + FALSE, INFINITE); + switch (waitResult) + { + /* CAN reception event. */ + case WAIT_OBJECT_0 + 0: /*lint !e835 */ + /* Empty out the queue with received events. */ + while (PCanUsbLibFuncRead(pCanUsbChannelLookup[pCanUsbSettings.channel], + &rxLibMsg, NULL) == PCAN_ERROR_OK) + { + /* Only process events that contain a CAN message with a 11-bit or 29-bit + * identifier. + */ + if ((rxLibMsg.MSGTYPE == PCAN_MESSAGE_STANDARD) || + (rxLibMsg.MSGTYPE == PCAN_MESSAGE_EXTENDED)) + { + /* Convert CAN mesage from PCAN-Basic format to the one of the CAN driver + * module. + */ + rxMsg.id = rxLibMsg.ID; + if (rxLibMsg.MSGTYPE == PCAN_MESSAGE_EXTENDED) + { + rxMsg.id |= CAN_MSG_EXT_ID_MASK; + } + rxMsg.dlc = rxLibMsg.LEN; + for (uint8_t idx = 0; idx < rxMsg.dlc; idx++) + { + rxMsg.data[idx] = rxLibMsg.DATA[idx]; + } + + /* Trigger message reception event(s). */ + pEvents = pCanUsbEventsList; + for (uint32_t idx = 0; idx < pCanUsbEventsEntries; idx++) + { + if (pEvents != NULL) + { + if (pEvents->MsgRxed != NULL) + { + pEvents->MsgRxed(&rxMsg); + } + /* Move on to the next entry in the list. */ + pEvents++; + } + } + } + } + break; + + /* Termination event. */ + default: + case WAIT_OBJECT_0 + 1: /*lint !e835 */ + /* Stop thread. */ + running = false; + break; + } + } + /* Exit thread. */ + return 0; +} /*** end of PCanUsbReceptionThread ***/ + + +/************************************************************************************//** +** \brief Loads the PCAN-Basic DLL and initializes the API function pointers. +** +****************************************************************************************/ +static void PCanUsbLibLoadDll(void) +{ + /* Start out by resetting the API function pointers. */ + pCanUsbLibFuncInitializePtr = NULL; + pCanUsbLibFuncpUninitializePtr = NULL; + pCanUsbLibFuncGetStatusPtr = NULL; + pCanUsbLibFuncSetValuePtr = NULL; + pCanUsbLibFuncReadPtr = NULL; + pCanUsbLibFuncWritePtr = NULL; + pCanUsbLibFuncFilterMessagesPtr = NULL; + + /* Attempt to load the library and obtain a handle to it. */ + pCanUsbDllHandle = LoadLibrary("PCANBasic"); + + /* Assert libary handle. */ + assert(pCanUsbDllHandle != NULL); + + /* Only continue if the library was successfully loaded */ + if (pCanUsbDllHandle != NULL) /*lint !e774 */ + { + /* Set CAN_Initialize function pointer. */ + pCanUsbLibFuncInitializePtr = (tPCanUsbLibFuncInitialize)GetProcAddress(pCanUsbDllHandle, "CAN_Initialize"); + /* Set CAN_Uninitialize function pointer. */ + pCanUsbLibFuncpUninitializePtr = (tPCanUsbLibFuncpUninitialize)GetProcAddress(pCanUsbDllHandle, "CAN_Uninitialize"); + /* Set CAN_GetStatus function pointer. */ + pCanUsbLibFuncGetStatusPtr = (tPCanUsbLibFuncGetStatus)GetProcAddress(pCanUsbDllHandle, "CAN_GetStatus"); + /* Set CAN_SetValue function pointer. */ + pCanUsbLibFuncSetValuePtr = (tPCanUsbLibFuncSetValue)GetProcAddress(pCanUsbDllHandle, "CAN_SetValue"); + /* Set CAN_Read function pointer. */ + pCanUsbLibFuncReadPtr = (tPCanUsbLibFuncRead)GetProcAddress(pCanUsbDllHandle, "CAN_Read"); + /* Set CAN_Write function pointer. */ + pCanUsbLibFuncWritePtr = (tPCanUsbLibFuncWrite)GetProcAddress(pCanUsbDllHandle, "CAN_Write"); + /* Set CAN_FilterMessages function pointer. */ + pCanUsbLibFuncFilterMessagesPtr = (tPCanUsbLibFuncFilterMessages)GetProcAddress(pCanUsbDllHandle, "CAN_FilterMessages"); + } +} /*** end of PCanUsbLibLoadDll ***/ + + +/************************************************************************************//** +** \brief Unloads the PCAN-Basic DLL and resets the API function pointers. +** +****************************************************************************************/ +static void PCanUsbLibUnloadDll(void) +{ + /* Reset the API function pointers. */ + pCanUsbLibFuncInitializePtr = NULL; + pCanUsbLibFuncpUninitializePtr = NULL; + pCanUsbLibFuncGetStatusPtr = NULL; + pCanUsbLibFuncSetValuePtr = NULL; + pCanUsbLibFuncReadPtr = NULL; + pCanUsbLibFuncWritePtr = NULL; + pCanUsbLibFuncFilterMessagesPtr = NULL; + + /* Unload the library and invalidate its handle. */ + if (pCanUsbDllHandle != NULL) + { + (void)FreeLibrary(pCanUsbDllHandle); + pCanUsbDllHandle = NULL; + } +} /*** end of PCanUsbLibUnloadDll ***/ + + +/************************************************************************************//** +** \brief Initializes a PCAN Channel. +** \param Channel The handle of a PCAN Channel. +** \param Btr0Btr1 The speed for the communication (BTR0BTR1 code). +** \param HwType The type of the Non-Plug-and-Play hardware and its operation mode. +** \param IOPort The I/O address for the parallel port of the Non-Plug-and-Play +** hardware. +** \param Interrupt The Interrupt number of the parallel port of the Non-Plug- +** and-Play hardware. +** \return The return value is a TPCANStatus code. PCAN_ERROR_OK is returned on +** success. +** +****************************************************************************************/ +static TPCANStatus PCanUsbLibFuncInitialize(TPCANHandle Channel, TPCANBaudrate Btr0Btr1, + TPCANType HwType, DWORD IOPort, + WORD Interrupt) +{ + /* set result to error. */ + TPCANStatus result = PCAN_ERROR_INITIALIZE; + + /* Check function pointer and library handle. */ + assert(pCanUsbLibFuncInitializePtr != NULL); + assert(pCanUsbDllHandle != NULL); + + /* Only continue with valid function pointer and library handle. */ + if ((pCanUsbLibFuncInitializePtr != NULL) && (pCanUsbDllHandle != NULL)) /*lint !e774 */ + { + /* Call library function. */ + result = pCanUsbLibFuncInitializePtr(Channel, Btr0Btr1, HwType, IOPort, Interrupt); + } + /* Give the result back to the caller. */ + return result; +} /*** end of PCanUsbLibFuncInitialize ***/ + + +/************************************************************************************//** +** \brief Uninitializes a PCAN Channel. +** \param Channel The handle of a PCAN Channel. +** \return The return value is a TPCANStatus code. PCAN_ERROR_OK is returned on +** success. +** +****************************************************************************************/ +static TPCANStatus PCanUsbLibFuncpUninitialize(TPCANHandle Channel) +{ + /* set result to error. */ + TPCANStatus result = PCAN_ERROR_INITIALIZE; + + /* Check function pointer and library handle. */ + assert(pCanUsbLibFuncpUninitializePtr != NULL); + assert(pCanUsbDllHandle != NULL); + + /* Only continue with valid function pointer and library handle. */ + if ((pCanUsbLibFuncpUninitializePtr != NULL) && (pCanUsbDllHandle != NULL)) /*lint !e774 */ + { + /* Call library function. */ + result = pCanUsbLibFuncpUninitializePtr(Channel); + } + /* Give the result back to the caller. */ + return result; +} /*** end of PCanUsbLibFuncpUninitialize ***/ + + +/************************************************************************************//** +** \brief Gets the current BUS status of a PCAN Channel. +** \param Channel The handle of a PCAN Channel. +** \return The return value is a TPCANStatus code. PCAN_ERROR_OK is returned on +** success. +** +****************************************************************************************/ +static TPCANStatus PCanUsbLibFuncGetStatus(TPCANHandle Channel) +{ + /* set result to error. */ + TPCANStatus result = PCAN_ERROR_INITIALIZE; + + /* Check function pointer and library handle. */ + assert(pCanUsbLibFuncGetStatusPtr != NULL); + assert(pCanUsbDllHandle != NULL); + + /* Only continue with valid function pointer and library handle. */ + if ((pCanUsbLibFuncGetStatusPtr != NULL) && (pCanUsbDllHandle != NULL)) /*lint !e774 */ + { + /* Call library function. */ + result = pCanUsbLibFuncGetStatusPtr(Channel); + } + /* Give the result back to the caller. */ + return result; +} /*** end of PCanUsbLibFuncGetStatus ***/ + + +/************************************************************************************//** +** \brief Sets a configuration or information value within a PCAN Channel. +** \param Channel The handle of a PCAN Channel. +** \param Parameter The code of the value to be set . +** \param Buffer The buffer containing the value to be set. +** \param BufferLength The length in bytes of the given buffer. +** \return The return value is a TPCANStatus code. PCAN_ERROR_OK is returned on +** success. +** +****************************************************************************************/ +static TPCANStatus PCanUsbLibFuncSetValue(TPCANHandle Channel, TPCANParameter Parameter, + void * Buffer, DWORD BufferLength) +{ + /* set result to error. */ + TPCANStatus result = PCAN_ERROR_INITIALIZE; + + /* Check function pointer and library handle. */ + assert(pCanUsbLibFuncSetValuePtr != NULL); + assert(pCanUsbDllHandle != NULL); + + /* Only continue with valid function pointer and library handle. */ + if ((pCanUsbLibFuncSetValuePtr != NULL) && (pCanUsbDllHandle != NULL)) /*lint !e774 */ + { + /* Call library function. */ + result = pCanUsbLibFuncSetValuePtr(Channel, Parameter, Buffer, BufferLength); + } + /* Give the result back to the caller. */ + return result; +} /*** end of PCanUsbLibFuncSetValue ***/ + + +/************************************************************************************//** +** \brief Reads a CAN message from the receive queue of a PCAN Channel. +** \param Channel The handle of a PCAN Channel. +** \param MessageBuffer A TPCANMsg buffer to store the CAN message. +** \param TimestampBuffer A TPCANTimestamp buffer to get the reception time of the +** message. +** \return The return value is a TPCANStatus code. PCAN_ERROR_OK is returned on +** success. +** +****************************************************************************************/ +static TPCANStatus PCanUsbLibFuncRead(TPCANHandle Channel, TPCANMsg * MessageBuffer, + TPCANTimestamp * TimestampBuffer) +{ + /* set result to error. */ + TPCANStatus result = PCAN_ERROR_INITIALIZE; + + /* Check function pointer and library handle. */ + assert(pCanUsbLibFuncReadPtr != NULL); + assert(pCanUsbDllHandle != NULL); + + /* Only continue with valid function pointer and library handle. */ + if ((pCanUsbLibFuncReadPtr != NULL) && (pCanUsbDllHandle != NULL)) /*lint !e774 */ + { + /* Call library function. */ + result = pCanUsbLibFuncReadPtr(Channel, MessageBuffer, TimestampBuffer); + } + /* Give the result back to the caller. */ + return result; +} /*** end of PCanUsbLibFuncRead ***/ + + +/************************************************************************************//** +** \brief Transmits a CAN message. +** \param Channel The handle of a PCAN Channel. +** \param MessageBuffer A TPCANMsg buffer containing the CAN message to be sent. +** \return The return value is a TPCANStatus code. PCAN_ERROR_OK is returned on +** success. +** +****************************************************************************************/ +static TPCANStatus PCanUsbLibFuncWrite(TPCANHandle Channel, TPCANMsg * MessageBuffer) +{ + /* set result to error. */ + TPCANStatus result = PCAN_ERROR_INITIALIZE; + + /* Check function pointer and library handle. */ + assert(pCanUsbLibFuncWritePtr != NULL); + assert(pCanUsbDllHandle != NULL); + + /* Only continue with valid function pointer and library handle. */ + if ((pCanUsbLibFuncWritePtr != NULL) && (pCanUsbDllHandle != NULL)) /*lint !e774 */ + { + /* Call library function. */ + result = pCanUsbLibFuncWritePtr(Channel, MessageBuffer); + } + /* Give the result back to the caller. */ + return result; +} /*** end of PCanUsbLibFuncWrite ***/ + + +/************************************************************************************//** +** \brief Configures the reception filter. +** \param Channel The handle of a PCAN Channel. +** \param FromID The lowest CAN ID wanted to be received. +** \param ToID The highest CAN ID wanted to be received. +** \param Mode The type of the filter being set. +** \return The return value is a TPCANStatus code. PCAN_ERROR_OK is returned on +** success. +** +****************************************************************************************/ +static TPCANStatus PCanUsbLibFuncFilterMessages(TPCANHandle Channel, DWORD FromID, + DWORD ToID, TPCANMode Mode) +{ + /* set result to error. */ + TPCANStatus result = PCAN_ERROR_INITIALIZE; + + /* Check function pointer and library handle. */ + assert(pCanUsbLibFuncFilterMessagesPtr != NULL); + assert(pCanUsbDllHandle != NULL); + + /* Only continue with valid function pointer and library handle. */ + if ((pCanUsbLibFuncFilterMessagesPtr != NULL) && (pCanUsbDllHandle != NULL)) /*lint !e774 */ + { + /* Call library function. */ + result = pCanUsbLibFuncFilterMessagesPtr(Channel, FromID, ToID, Mode); + } + /* Give the result back to the caller. */ + return result; +} /*** end of PCanUsbLibFuncFilterMessages ***/ + + /*********************************** end of pcanusb.c **********************************/ diff --git a/Host/libopenblt.dll b/Host/libopenblt.dll index 37dbbbb7..e1ad8195 100644 Binary files a/Host/libopenblt.dll and b/Host/libopenblt.dll differ