iatr@787: /* iatr@787: This file is part of CanFestival, a library implementing CanOpen Stack. iatr@787: iatr@787: Copyright (C): Edouard TISSERANT and Francis DUPIN iatr@787: iatr@787: See COPYING file for copyrights details. iatr@787: iatr@787: This library is free software; you can redistribute it and/or iatr@787: modify it under the terms of the GNU Lesser General Public iatr@787: License as published by the Free Software Foundation; either iatr@787: version 2.1 of the License, or (at your option) any later version. iatr@787: iatr@787: This library is distributed in the hope that it will be useful, iatr@787: but WITHOUT ANY WARRANTY; without even the implied warranty of iatr@787: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU iatr@787: Lesser General Public License for more details. iatr@787: iatr@787: You should have received a copy of the GNU Lesser General Public iatr@787: License along with this library; if not, write to the Free Software iatr@787: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA iatr@787: */ iatr@787: iatr@787: iatr@787: /* iatr@787: Wrapper Layer for CANFestival to interact with IXXAT VCI V3.X.X Drivers (vcisdk.lib) iatr@787: Provides external references for win32 library see win32.c (CanFestival-3) iatr@787: iatr@787: http://www.ixxat.com/download_vci_v3_en.html iatr@787: iatr@787: Currently the VCI CAN driver for Windows supports the following IXXAT interfaces: iatr@787: iatr@787: PC-I 04/PCI iatr@787: iPC-I 320/PCI II iatr@787: iPC-I 165/PCI iatr@787: iPC-I XC16/PCI iatr@787: iPC-I XC16/PMC iatr@787: iPC-I XC16/PCIe iatr@787: USB-to-CAN compact iatr@787: USB-to-CAN II iatr@787: CAN-IB100/PCIe iatr@787: CAN-IB200/PCIe iatr@787: CAN-IB120/PCIe Mini iatr@787: CAN-IB130/PCIe 104 iatr@787: CAN-IB230/PCIe 104 iatr@787: CAN@net II/VCI iatr@787: CANblue II iatr@787: FR-IB100/PCIe (only in combination with VCI V2.20) iatr@787: tinCAN 161 iatr@787: iatr@787: */ iatr@787: iatr@787: iatr@787: /************************************************************************* iatr@787: ** iatr@787: ************************************************************************** iatr@787: ** iatr@787: ** File: can_ixxat_win32.c iatr@787: ** Summary: Wrapper to encapsulate handling of VCI3 iatr@787: ** Include vcisdk.lib iatr@787: ** iatr@787: ************************************************************************** iatr@787: ************************************************************************** iatr@787: ** iatr@787: ** Functions: canOpen_driver iatr@787: ** canReceive_driver iatr@787: ** TimerProc1 iatr@787: ** canClose_driver iatr@787: ** canSend_drive iatr@787: ** iatr@787: **/ iatr@787: iatr@787: #include iatr@787: #include "can_driver.h" iatr@787: #include "def.h" iatr@787: #include "winuser.h" iatr@787: iatr@787: // Include a path to the following header files provided with VCI V3.X.X iatr@787: // ...sdk/Microsoft_VisualC/inc iatr@787: #include "vcinpl.h" iatr@787: #include "VCI3.h" iatr@787: #include "vcitype.h" iatr@787: #include "vciguid.h" iatr@787: #include "vcierr.h" iatr@787: iatr@787: iatr@787: iatr@787: /************************************************************************ iatr@787: ** bus status polling cycle milliseconds iatr@787: *************************************************************************/ iatr@787: #define STATUS_POLLING_CYCLE 1000 iatr@787: iatr@787: /************************************************************************* iatr@787: ** function prototypes iatr@787: *************************************************************************/ iatr@787: void CALLBACK TimerProc1(void* lpParametar, BOOL TimerOrWaitFired ); iatr@787: void Display_Error(HRESULT hResult); iatr@787: iatr@787: iatr@787: /************************************************************************* iatr@787: ** static variables iatr@787: *************************************************************************/ iatr@787: static HANDLE hDevice; // device handle iatr@787: static LONG lCtrlNo; // controller number iatr@787: static HANDLE hCanCtl; // controller handle iatr@787: static HANDLE hCanChn; // channel handle iatr@787: static LONG lMustQuit = 0; // quit flag for the receive thread iatr@787: static HANDLE hTimerHandle; // timer handle iatr@787: iatr@787: /************************************************************************* iatr@787: ** datatypes iatr@787: *************************************************************************/ iatr@787: iatr@787: struct sLook_up_table iatr@787: { iatr@787: char baud_rate[20]; iatr@787: UINT8 bt0; iatr@787: UINT8 bt1; iatr@787: }; iatr@787: iatr@787: struct sInterface_lookup_table iatr@787: { iatr@787: char board_num[10]; iatr@787: UINT8 num; iatr@787: }; iatr@787: iatr@787: /************************************************************************* iatr@787: ** iatr@787: ** Function : canOpen_driver iatr@787: ** iatr@787: ** Description : Initializes the Control and Message Channels iatr@787: ** Parameters : s_BOARD *board - pointer to board information iatr@787: ** Returnvalue : (CAN_HANDLE)board - handle for CAN controller iatr@787: ** iatr@787: *************************************************************************/ iatr@787: CAN_HANDLE __stdcall canOpen_driver(s_BOARD *board) iatr@787: { iatr@787: HANDLE hEnumerator; // enumerator handle iatr@787: VCIDEVICEINFO VCIDeviceInfo; // device info iatr@787: HRESULT hResult; iatr@787: int index, boardNum; iatr@787: BOOL bResult; iatr@787: iatr@787: struct sLook_up_table sBitRate_lookup[9] = { iatr@787: {"10K",0x31,0x1C}, iatr@787: {"20K",0x18,0x1C}, iatr@787: {"50K",0x09,0x1C}, iatr@787: {"100K",0x04,0x1C}, iatr@787: {"125K",0x03,0x1C}, iatr@787: {"250K",0x01,0x1C}, iatr@787: {"500K",0x00,0x1C}, iatr@787: {"800K",0x00,0x16}, iatr@787: {"1M",0x00,0x14}}; iatr@787: iatr@787: struct sInterface_lookup_table sInterfaceList[4]={ iatr@787: {"vcan0",0}, iatr@787: {"vcan1",1}, iatr@787: {"vcan2",2}, iatr@787: {"vcan3",3}}; iatr@787: iatr@787: for (boardNum =0 ; boardNum<4;boardNum++) // determine canline selected iatr@787: { iatr@787: if (strcmp(sInterfaceList[boardNum].board_num,board->busname )==0) iatr@787: break; iatr@787: } iatr@787: iatr@787: for (index = 0; index < 10; ++index) // determine baudrate iatr@787: { iatr@787: if (strcmp(sBitRate_lookup[index].baud_rate,board->baudrate)==0) iatr@787: break; iatr@787: } iatr@787: iatr@787: if (index == 9) iatr@787: { iatr@787: MSG_ERR_DRV("IXXAT::open: The given baudrate %S is invalid.", baud_rate); iatr@787: return NULL ; iatr@787: } iatr@787: iatr@787: iatr@787: /* iatr@787: ** The following can be used when the client has multiple CAN interfaces to slect from, and does not wish to use the iatr@787: ** selection dialog box iatr@787: /* iatr@787: iatr@787: /* iatr@787: hResult= vciEnumDeviceOpen(&hEnumerator); iatr@787: // This loop will increment the index of the device list and returns the decription of the CAN line chose by user iatr@787: if (hResult== VCI_OK) iatr@787: { iatr@787: for (index1=0; index1 <= sInterfaceList[boardNum].num; index1++){ iatr@787: hResult=vciEnumDeviceNext(hEnumerator, &VCIDeviceInfo); iatr@787: } iatr@787: } iatr@787: printf("Device Selected: %s %s\n",VCIDeviceInfo.Manufacturer, VCIDeviceInfo.Description); iatr@787: if (hResult== VCI_OK) iatr@787: hResult=vciEnumDeviceClose(hEnumerator); iatr@787: iatr@787: if (hResult== VCI_OK) iatr@787: hResult= vciDeviceOpen(&VCIDeviceInfo.VciObjectId, &hDevice); iatr@787: */ iatr@787: iatr@787: iatr@787: iatr@787: /* iatr@787: ** Display Interface Selection Dialog Box iatr@787: */ iatr@787: hResult= vciDeviceOpenDlg(0, &hDevice); iatr@787: iatr@787: /* iatr@787: ** Establish and activate the message Channel iatr@787: */ iatr@787: if (hResult== VCI_OK) iatr@787: hResult= canChannelOpen(hDevice, 0, TRUE, &hCanChn); iatr@787: // Select Rx fifo size, Rx threshold, Tx fifo size, Tx threshold iatr@787: if (hResult== VCI_OK) iatr@787: hResult=canChannelInitialize( hCanChn, 1024, 1,128,1); iatr@787: iatr@787: if (hResult== VCI_OK) iatr@787: hResult=canChannelActivate(hCanChn, TRUE); iatr@787: iatr@787: iatr@787: /* iatr@787: ** Establish and Activate the Contol Channel iatr@787: */ iatr@787: if (hResult== VCI_OK) iatr@787: hResult=canControlOpen(hDevice, 0, &hCanCtl); iatr@787: iatr@787: // Select 11 or 29 bit IDs, Select operating mode iatr@787: if (hResult== VCI_OK) iatr@787: hResult=canControlInitialize( hCanCtl, CAN_OPMODE_STANDARD | CAN_OPMODE_ERRFRAME, sBitRate_lookup[index].bt0, sBitRate_lookup[index].bt1 ); iatr@787: iatr@787: iatr@787: // With VCI it is possible to filter IDs, See VCI V3 manual. The following will accept all IDs iatr@787: if (hResult== VCI_OK) iatr@787: hResult= canControlSetAccFilter( hCanCtl, FALSE, CAN_ACC_CODE_ALL, CAN_ACC_MASK_ALL); iatr@787: iatr@787: if (hResult== VCI_OK) iatr@787: hResult=canControlStart(hCanCtl, TRUE); iatr@787: iatr@787: if (hResult!=VCI_OK) iatr@787: { iatr@787: Display_Error(hResult); iatr@787: return NULL; iatr@787: } iatr@787: iatr@787: iatr@787: /* iatr@787: ** Create timer to poll bus status iatr@787: */ iatr@787: bResult= CreateTimerQueueTimer( iatr@787: & hTimerHandle, iatr@787: NULL, iatr@787: TimerProc1, // Callback function iatr@787: NULL, iatr@787: 0, iatr@787: STATUS_POLLING_CYCLE, iatr@787: WT_EXECUTEINIOTHREAD iatr@787: ); iatr@787: iatr@787: return (CAN_HANDLE)board; iatr@787: } iatr@787: iatr@787: iatr@787: /************************************************************************* iatr@787: ** iatr@787: ** Function : canReceive_driver iatr@787: ** iatr@787: ** Description : Transfers RX messages to Festival application iatr@787: ** Parameters : CAN_HANDLE inst - handle for CAN controller iatr@787: Message *m - pointer to Message struct iatr@787: ** Returnvalue : hResult - VCI_OK if success iatr@787: ** iatr@787: *************************************************************************/ iatr@787: UNS8 __stdcall canReceive_driver(CAN_HANDLE inst, Message *m) iatr@787: { iatr@787: HRESULT hResult; iatr@787: CANMSG rCanMsg; iatr@787: //Read message from the receive buffer iatr@787: hResult=canChannelReadMessage( hCanChn, INFINITE, &rCanMsg ); iatr@787: if (hResult !=VCI_OK ) iatr@787: return 1; iatr@787: iatr@787: m->cob_id = rCanMsg.dwMsgId; iatr@787: m->len = rCanMsg.uMsgInfo.Bits.dlc; iatr@787: m->rtr = rCanMsg.uMsgInfo.Bits.rtr; iatr@787: if (m->rtr == NOT_A_REQUEST) iatr@787: memcpy(m->data, rCanMsg.abData , m->len); iatr@787: return (UNS8)hResult; iatr@787: } iatr@787: iatr@787: /************************************************************************* iatr@787: ** iatr@787: ** Function : canSend_driver iatr@787: ** iatr@787: ** Description : Transfers RX messages to Interface iatr@787: ** Parameters : CAN_HANDLE inst - handle for CAN controller iatr@787: ** Message *m - pointer to Message struct iatr@787: ** Returnvalue : hResult - VCI_OK if success iatr@787: ** iatr@787: *************************************************************************/ iatr@787: UNS8 __stdcall canSend_driver(CAN_HANDLE inst, Message const *m) iatr@787: { iatr@787: HRESULT hResult; iatr@787: CANMSG sCanMsg; iatr@787: iatr@787: sCanMsg.uMsgInfo.Bytes.bType = CAN_MSGTYPE_DATA; iatr@787: sCanMsg.uMsgInfo.Bytes.bFlags = CAN_MAKE_MSGFLAGS(8,0,0,0,0); iatr@787: sCanMsg.uMsgInfo.Bits.srr = 0; iatr@787: sCanMsg.dwTime = 0; iatr@787: sCanMsg.dwMsgId = m->cob_id ; iatr@787: memcpy(sCanMsg.abData,m->data, m->len); iatr@787: sCanMsg.uMsgInfo.Bits.dlc = m->len; iatr@787: sCanMsg.uMsgInfo.Bits.rtr=m->rtr; iatr@787: iatr@787: // write the CAN message into the transmit FIFO without waiting for transmission iatr@787: hResult = canChannelPostMessage(hCanChn, &sCanMsg); iatr@787: iatr@787: return (UNS8)hResult; iatr@787: } iatr@787: iatr@787: iatr@787: iatr@787: iatr@787: /************************************************************************* iatr@787: ** iatr@787: ** Function : canClose_driver iatr@787: ** iatr@787: ** Description : Close the message and control channel iatr@787: ** Parameters : CAN_HANDLE inst - handle for CAN controller iatr@787: ** Returnvalue : iatr@787: ** iatr@787: *************************************************************************/ iatr@787: int __stdcall canClose_driver(CAN_HANDLE inst) iatr@787: { iatr@787: printf("CAN close \n"); iatr@787: canControlReset(hCanCtl); iatr@787: canChannelClose(hCanChn); iatr@787: canControlClose(hCanCtl); iatr@787: vciDeviceClose(hDevice); iatr@787: DeleteTimerQueueTimer(NULL,hTimerHandle,NULL); iatr@787: return 1; iatr@787: } iatr@787: iatr@787: iatr@787: /************************************************************************* iatr@787: ** iatr@787: ** Function : canChangeBaudRate_driver iatr@787: ** iatr@787: ** Description : Changes the Baudrate of the interface (not supported) iatr@787: ** Parameters : iatr@787: ** Returnvalue : iatr@787: ** iatr@787: *************************************************************************/ iatr@787: UNS8 __stdcall canChangeBaudRate_driver( CAN_HANDLE fd, char* baud) iatr@787: { iatr@787: //printf("canChangeBaudRate not yet supported by this driver\n"); iatr@787: return 0; iatr@787: } iatr@787: iatr@787: iatr@787: /************************************************************************* iatr@787: ** iatr@787: ** Function : TimerProc1 iatr@787: ** iatr@787: ** Description : Basic Polling of the the canline status, iatr@787: ** print debug message for buffer overflow, and BUSOFF condition iatr@787: ** Parameters : void* lpParametar, BOOL TimerOrWaitFired iatr@787: ** Returnvalue : none iatr@787: ** iatr@787: *************************************************************************/ iatr@787: void CALLBACK TimerProc1(void* lpParametar, BOOL TimerOrWaitFired ) iatr@787: { iatr@787: HRESULT hResult; iatr@787: CANLINESTATUS canStatus; iatr@787: iatr@787: iatr@787: /* Establish CAN controller status */ iatr@787: hResult = canControlGetStatus ( hCanCtl, &canStatus); iatr@787: if (hResult!=VCI_OK) iatr@787: printf("Error did not read CAN STATUS\n"); iatr@787: switch ( canStatus.dwStatus) iatr@787: { iatr@787: case CAN_STATUS_OVRRUN: iatr@787: printf("Overrun of the recieve buffer\n"); iatr@787: break; iatr@787: case CAN_STATUS_ERRLIM: iatr@787: printf("Overrun of the CAN controller error counter \n"); iatr@787: break; iatr@787: case CAN_STATUS_BUSOFF: iatr@787: printf("CAN status: BUSOFF"); iatr@787: break; iatr@787: case CAN_STATUS_ININIT: iatr@787: break; iatr@787: case (CAN_STATUS_BUSOFF)+(CAN_STATUS_ININIT): iatr@787: printf("CAN status: BUSOFF\n"); iatr@787: iatr@787: /* iatr@787: ** Bus off recovery should come after a software reset, and 128*11 recessive bits. iatr@787: ** This can only happen when an Error-Active node sends an active error flag, iatr@787: ** and other nodes respond with Error Echo Flag iatr@787: */ iatr@787: break; iatr@787: default: iatr@787: break; iatr@787: } iatr@787: }; iatr@787: iatr@787: iatr@787: /************************************************************************* iatr@787: ** iatr@787: ** Function : Display_Error iatr@787: ** iatr@787: ** Description : Display the CANline Error iatr@787: ** Parameters : HANDLE hResult iatr@787: ** Returnvalue : none iatr@787: ** iatr@787: *************************************************************************/ iatr@787: void Display_Error(HRESULT hResult ) iatr@787: { iatr@787: char szError[VCI_MAX_ERRSTRLEN]; iatr@787: if (hResult != NO_ERROR) iatr@787: { iatr@787: if (hResult == -1) iatr@787: hResult = GetLastError(); iatr@787: szError[0] = 0; iatr@787: vciFormatError(hResult, szError, sizeof(szError)); iatr@787: printf("Error Establishing CAN channel, Error Code: %s\n",szError); iatr@787: } iatr@787: }