drivers/can_ixxat_win32/can_ixxat_win.c
changeset 788 6121ebff4da6
parent 787 e13fa74d169c
equal deleted inserted replaced
786:8dbe0aec4f36 788:6121ebff4da6
       
     1 /*
       
     2 This file is part of CanFestival, a library implementing CanOpen Stack.
       
     3 
       
     4 Copyright (C): Edouard TISSERANT and Francis DUPIN
       
     5 
       
     6 See COPYING file for copyrights details.
       
     7 
       
     8 This library is free software; you can redistribute it and/or
       
     9 modify it under the terms of the GNU Lesser General Public
       
    10 License as published by the Free Software Foundation; either
       
    11 version 2.1 of the License, or (at your option) any later version.
       
    12 
       
    13 This library is distributed in the hope that it will be useful,
       
    14 but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    16 Lesser General Public License for more details.
       
    17 
       
    18 You should have received a copy of the GNU Lesser General Public
       
    19 License along with this library; if not, write to the Free Software
       
    20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    21 */
       
    22 
       
    23 
       
    24 /*
       
    25 	Wrapper Layer for CANFestival to interact with IXXAT VCI V3.X.X Drivers (vcisdk.lib)
       
    26 	Provides external references for win32 library see win32.c (CanFestival-3)
       
    27 
       
    28 	http://www.ixxat.com/download_vci_v3_en.html
       
    29 
       
    30 	Currently the VCI CAN driver for Windows supports the following IXXAT interfaces:
       
    31 
       
    32 	PC-I 04/PCI
       
    33 	iPC-I 320/PCI II
       
    34 	iPC-I 165/PCI
       
    35 	iPC-I XC16/PCI
       
    36 	iPC-I XC16/PMC
       
    37 	iPC-I XC16/PCIe
       
    38 	USB-to-CAN compact
       
    39 	USB-to-CAN II
       
    40 	CAN-IB100/PCIe
       
    41 	CAN-IB200/PCIe
       
    42 	CAN-IB120/PCIe Mini
       
    43 	CAN-IB130/PCIe 104
       
    44 	CAN-IB230/PCIe 104
       
    45 	CAN@net II/VCI
       
    46 	CANblue II
       
    47 	FR-IB100/PCIe (only in combination with VCI V2.20)
       
    48 	tinCAN 161
       
    49 
       
    50 */
       
    51 
       
    52 
       
    53 /*************************************************************************
       
    54 **    
       
    55 **************************************************************************
       
    56 **
       
    57 **    File: can_ixxat_win32.c
       
    58 **    Summary: Wrapper to encapsulate handling of VCI3
       
    59 **	  Include vcisdk.lib	
       
    60 **
       
    61 **************************************************************************
       
    62 **************************************************************************
       
    63 **
       
    64 **  Functions:  canOpen_driver
       
    65 **              canReceive_driver
       
    66 **              TimerProc1
       
    67 **              canClose_driver
       
    68 **				canSend_drive
       
    69 **				
       
    70 **/
       
    71 
       
    72 #include <stdio.h> 
       
    73 #include "can_driver.h"
       
    74 #include "def.h"
       
    75 #include "winuser.h"
       
    76 
       
    77 //  Include a path to the following header files provided with VCI V3.X.X
       
    78 //      ...sdk/Microsoft_VisualC/inc
       
    79 #include "vcinpl.h" 
       
    80 #include "VCI3.h"  
       
    81 #include "vcitype.h"
       
    82 #include "vciguid.h"
       
    83 #include "vcierr.h" 
       
    84 
       
    85 
       
    86 
       
    87 /************************************************************************
       
    88 **   bus status polling cycle  milliseconds
       
    89 *************************************************************************/
       
    90 #define STATUS_POLLING_CYCLE 1000
       
    91 
       
    92 /*************************************************************************
       
    93 **   function prototypes
       
    94 *************************************************************************/
       
    95 void CALLBACK TimerProc1(void* lpParametar, BOOL TimerOrWaitFired );
       
    96 void Display_Error(HRESULT hResult);
       
    97 
       
    98 
       
    99 /*************************************************************************
       
   100 **   static variables 
       
   101 *************************************************************************/
       
   102 static HANDLE hDevice;       // device handle
       
   103 static LONG   lCtrlNo;       // controller number
       
   104 static HANDLE hCanCtl;       // controller handle 
       
   105 static HANDLE hCanChn;       // channel handle
       
   106 static LONG   lMustQuit = 0; // quit flag for the receive thread
       
   107 static HANDLE hTimerHandle;  // timer handle 
       
   108 
       
   109 /*************************************************************************
       
   110 **    datatypes
       
   111 *************************************************************************/
       
   112  
       
   113 struct sLook_up_table
       
   114 {
       
   115 	char baud_rate[20];
       
   116 	UINT8 bt0;
       
   117 	UINT8 bt1; 
       
   118 };
       
   119 
       
   120 struct sInterface_lookup_table
       
   121 {
       
   122 	char board_num[10];
       
   123 	UINT8 num;
       
   124 };
       
   125 
       
   126 /*************************************************************************
       
   127 **
       
   128 **    Function      : canOpen_driver
       
   129 **
       
   130 **    Description   : Initializes the Control and Message Channels
       
   131 **    Parameters    : s_BOARD *board		- pointer to board information
       
   132 **    Returnvalue   : (CAN_HANDLE)board		- handle for CAN controller 
       
   133 **   
       
   134 *************************************************************************/
       
   135 CAN_HANDLE __stdcall canOpen_driver(s_BOARD *board)
       
   136 {
       
   137     HANDLE        hEnumerator;     // enumerator handle
       
   138     VCIDEVICEINFO VCIDeviceInfo;   // device info
       
   139 	HRESULT hResult;
       
   140 	int index,  boardNum; 
       
   141 	BOOL bResult; 
       
   142 
       
   143 	struct sLook_up_table sBitRate_lookup[9] = {
       
   144 		{"10K",0x31,0x1C},
       
   145 		{"20K",0x18,0x1C},
       
   146 		{"50K",0x09,0x1C},
       
   147         {"100K",0x04,0x1C},
       
   148         {"125K",0x03,0x1C},
       
   149         {"250K",0x01,0x1C},
       
   150         {"500K",0x00,0x1C},
       
   151         {"800K",0x00,0x16},
       
   152         {"1M",0x00,0x14}};
       
   153 
       
   154 	struct sInterface_lookup_table sInterfaceList[4]={
       
   155 		{"vcan0",0},
       
   156 		{"vcan1",1},
       
   157 		{"vcan2",2},
       
   158 		{"vcan3",3}};
       
   159 	
       
   160 	for (boardNum =0 ; boardNum<4;boardNum++)   // determine canline selected 
       
   161 	{
       
   162 		if (strcmp(sInterfaceList[boardNum].board_num,board->busname )==0)
       
   163 			break;
       
   164 	}
       
   165 
       
   166 	for (index = 0; index < 10; ++index)       // determine baudrate 
       
   167 	{
       
   168 		if (strcmp(sBitRate_lookup[index].baud_rate,board->baudrate)==0)
       
   169           break;
       
   170 	}
       
   171 
       
   172 	if (index == 9)
       
   173 	{
       
   174 		MSG_ERR_DRV("IXXAT::open: The given baudrate %S is invalid.", baud_rate);
       
   175 		return NULL ;
       
   176 	}
       
   177 
       
   178 
       
   179 	/*
       
   180 	**	The following can be used when the client has multiple CAN interfaces to slect from, and does not wish to use the 
       
   181 	**  selection dialog box
       
   182 	/*
       
   183 
       
   184     /*		 
       
   185 	hResult= vciEnumDeviceOpen(&hEnumerator);
       
   186 	 // This loop will increment the index of the device list and returns the decription of the CAN line chose by user
       
   187 	if (hResult== VCI_OK)
       
   188 	{
       
   189 		for (index1=0; index1 <= sInterfaceList[boardNum].num; index1++){
       
   190 			hResult=vciEnumDeviceNext(hEnumerator, &VCIDeviceInfo);
       
   191 		}
       
   192 	}
       
   193 	printf("Device Selected: %s %s\n",VCIDeviceInfo.Manufacturer, VCIDeviceInfo.Description); 
       
   194 	if (hResult== VCI_OK)
       
   195 		hResult=vciEnumDeviceClose(hEnumerator);
       
   196 	
       
   197 	if (hResult== VCI_OK)
       
   198    		hResult= vciDeviceOpen(&VCIDeviceInfo.VciObjectId, &hDevice);
       
   199 	*/
       
   200 
       
   201 
       
   202 
       
   203 	/* 
       
   204 	**  Display Interface Selection Dialog Box 
       
   205 	*/
       
   206 	hResult= vciDeviceOpenDlg(0, &hDevice);
       
   207 
       
   208 	/*
       
   209 	**  Establish and activate the message Channel 
       
   210 	*/
       
   211 	if (hResult== VCI_OK)
       
   212 		hResult= canChannelOpen(hDevice, 0, TRUE, &hCanChn);
       
   213 	//  Select Rx fifo size, Rx threshold, Tx fifo size, Tx threshold
       
   214     if (hResult== VCI_OK)
       
   215 		hResult=canChannelInitialize( hCanChn, 1024, 1,128,1);  
       
   216 
       
   217     if (hResult== VCI_OK)
       
   218 	    hResult=canChannelActivate(hCanChn, TRUE);
       
   219 
       
   220 
       
   221 	/* 
       
   222 	** Establish and Activate the Contol Channel 
       
   223 	*/
       
   224     if (hResult== VCI_OK)
       
   225 		 hResult=canControlOpen(hDevice, 0, &hCanCtl);
       
   226 	 
       
   227 	//  Select 11 or 29 bit IDs, Select operating mode 
       
   228     if (hResult== VCI_OK)
       
   229 		hResult=canControlInitialize( hCanCtl, CAN_OPMODE_STANDARD | CAN_OPMODE_ERRFRAME, sBitRate_lookup[index].bt0, sBitRate_lookup[index].bt1 );
       
   230     
       
   231 	
       
   232 	//  With VCI it is possible to filter IDs, See VCI V3 manual. The following will accept all IDs
       
   233 	if (hResult== VCI_OK)
       
   234 	     hResult= canControlSetAccFilter( hCanCtl, FALSE, CAN_ACC_CODE_ALL, CAN_ACC_MASK_ALL);
       
   235     
       
   236 	if (hResult== VCI_OK)
       
   237 	    hResult=canControlStart(hCanCtl, TRUE);
       
   238   
       
   239 	if (hResult!=VCI_OK)
       
   240 	{
       
   241 		Display_Error(hResult);
       
   242 		return NULL; 
       
   243 	}
       
   244 
       
   245 
       
   246 	/*
       
   247 	**   Create timer to poll bus status 
       
   248 	*/  
       
   249 	bResult= CreateTimerQueueTimer(
       
   250 			& hTimerHandle,
       
   251 			NULL,
       
   252 			TimerProc1,    // Callback function
       
   253 			NULL,
       
   254 		    0,
       
   255 			STATUS_POLLING_CYCLE,
       
   256 			WT_EXECUTEINIOTHREAD
       
   257 		    );
       
   258 	
       
   259 	return (CAN_HANDLE)board;
       
   260 }
       
   261 
       
   262 
       
   263 /*************************************************************************
       
   264 **
       
   265 **    Function      : canReceive_driver 
       
   266 **
       
   267 **    Description   : Transfers RX messages to Festival application
       
   268 **    Parameters    : CAN_HANDLE inst		- handle for CAN controller 
       
   269 					  Message *m			- pointer to Message struct
       
   270 **    Returnvalue   : hResult				-   VCI_OK if success
       
   271 **   
       
   272 *************************************************************************/
       
   273 UNS8 __stdcall canReceive_driver(CAN_HANDLE inst, Message *m)
       
   274 {
       
   275     HRESULT hResult;
       
   276 	CANMSG rCanMsg;
       
   277 	//Read message from the receive buffer 
       
   278 	hResult=canChannelReadMessage( hCanChn, INFINITE, &rCanMsg );
       
   279 	if (hResult !=VCI_OK )
       
   280 		return 1; 		
       
   281 
       
   282 	m->cob_id =  rCanMsg.dwMsgId;   
       
   283 	m->len = rCanMsg.uMsgInfo.Bits.dlc;
       
   284 	m->rtr = rCanMsg.uMsgInfo.Bits.rtr;
       
   285 	   if (m->rtr == NOT_A_REQUEST)
       
   286 	    	memcpy(m->data, rCanMsg.abData , m->len);
       
   287 	return (UNS8)hResult; 
       
   288 }
       
   289 
       
   290 /*************************************************************************
       
   291 **
       
   292 **    Function      : canSend_driver 
       
   293 **
       
   294 **    Description   : Transfers RX messages to Interface 
       
   295 **    Parameters    : CAN_HANDLE inst		- handle for CAN controller 
       
   296 **					  Message *m			- pointer to Message struct
       
   297 **    Returnvalue   : hResult				-   VCI_OK if success
       
   298 **   
       
   299 *************************************************************************/
       
   300 UNS8 __stdcall canSend_driver(CAN_HANDLE inst, Message const *m)
       
   301 {
       
   302    	HRESULT hResult;
       
   303 	CANMSG sCanMsg; 
       
   304 
       
   305 	sCanMsg.uMsgInfo.Bytes.bType  = CAN_MSGTYPE_DATA;                
       
   306 	sCanMsg.uMsgInfo.Bytes.bFlags = CAN_MAKE_MSGFLAGS(8,0,0,0,0);
       
   307 	sCanMsg.uMsgInfo.Bits.srr     = 0;
       
   308 	sCanMsg.dwTime   = 0;
       
   309 	sCanMsg.dwMsgId  = m->cob_id ;                         
       
   310 	memcpy(sCanMsg.abData,m->data, m->len);	                     
       
   311 	sCanMsg.uMsgInfo.Bits.dlc = m->len;     
       
   312 	sCanMsg.uMsgInfo.Bits.rtr=m->rtr; 
       
   313 
       
   314 	// write the CAN message into the transmit FIFO without waiting for transmission
       
   315 	 hResult = canChannelPostMessage(hCanChn, &sCanMsg);
       
   316 
       
   317 	 return (UNS8)hResult; 
       
   318 }
       
   319 
       
   320 
       
   321 
       
   322 
       
   323 /*************************************************************************
       
   324 **
       
   325 **    Function      : canClose_driver 
       
   326 **
       
   327 **    Description   : Close the message and control channel
       
   328 **    Parameters    : CAN_HANDLE inst		- handle for CAN controller 
       
   329 **    Returnvalue   : 
       
   330 **   
       
   331 *************************************************************************/
       
   332  int __stdcall canClose_driver(CAN_HANDLE inst)
       
   333    {
       
   334 	printf("CAN close \n");
       
   335 	canControlReset(hCanCtl);
       
   336 	canChannelClose(hCanChn);
       
   337 	canControlClose(hCanCtl);
       
   338 	vciDeviceClose(hDevice);
       
   339 	DeleteTimerQueueTimer(NULL,hTimerHandle,NULL); 
       
   340    return 1;
       
   341    }
       
   342 
       
   343  
       
   344 /*************************************************************************
       
   345 **
       
   346 **    Function      : canChangeBaudRate_driver 
       
   347 **
       
   348 **    Description   : Changes the Baudrate of the interface (not supported) 
       
   349 **    Parameters    : 
       
   350 **    Returnvalue   : 
       
   351 **   
       
   352 *************************************************************************/
       
   353    UNS8 __stdcall canChangeBaudRate_driver( CAN_HANDLE fd, char* baud)
       
   354 	{
       
   355 	//printf("canChangeBaudRate not yet supported by this driver\n");
       
   356 	return 0;
       
   357 	}
       
   358 
       
   359 
       
   360  /*************************************************************************
       
   361 **
       
   362 **    Function      : TimerProc1 
       
   363 **
       
   364 **    Description   :  Basic Polling of the  the canline status,
       
   365 **					   print debug message for buffer overflow, and BUSOFF condition
       
   366 **    Parameters    :  void* lpParametar, BOOL TimerOrWaitFired
       
   367 **    Returnvalue   :  none 
       
   368 **   
       
   369 *************************************************************************/
       
   370    void CALLBACK TimerProc1(void* lpParametar, BOOL TimerOrWaitFired )
       
   371    {
       
   372 	   HRESULT hResult;
       
   373 	   CANLINESTATUS canStatus;
       
   374 	  
       
   375 
       
   376 	   /* Establish CAN controller status */
       
   377 	   hResult = canControlGetStatus ( hCanCtl, &canStatus);
       
   378 	   if (hResult!=VCI_OK)
       
   379 		   printf("Error did not read CAN STATUS\n"); 
       
   380 	   switch ( canStatus.dwStatus)
       
   381 	   {
       
   382 		   case CAN_STATUS_OVRRUN:
       
   383 			   printf("Overrun of the recieve buffer\n");
       
   384 			   break;
       
   385 		   case CAN_STATUS_ERRLIM:
       
   386 				printf("Overrun of the CAN controller error counter \n");
       
   387 			   break;
       
   388 		   case CAN_STATUS_BUSOFF:
       
   389 				printf("CAN status: BUSOFF");
       
   390 			   break; 
       
   391 		   case CAN_STATUS_ININIT:				
       
   392 			   break; 
       
   393 		   case (CAN_STATUS_BUSOFF)+(CAN_STATUS_ININIT):
       
   394 			   printf("CAN status: BUSOFF\n");
       
   395 			    
       
   396 	/* 
       
   397 	** Bus off recovery should come after a software reset, and 128*11 recessive bits.  
       
   398 	** This can only happen when an Error-Active node sends an active error flag,
       
   399 	** and other nodes respond with Error Echo Flag
       
   400 	*/
       
   401 			   break;
       
   402 		   default: 
       
   403 			   break; 
       
   404 	   }
       
   405    };
       
   406 
       
   407 
       
   408  /*************************************************************************
       
   409 **
       
   410 **    Function      : Display_Error
       
   411 **
       
   412 **    Description   :  Display the CANline Error
       
   413 **    Parameters    :  HANDLE hResult
       
   414 **    Returnvalue   :  none 
       
   415 **   
       
   416 *************************************************************************/
       
   417 	void Display_Error(HRESULT hResult )
       
   418    {
       
   419 	char szError[VCI_MAX_ERRSTRLEN];
       
   420 	if (hResult != NO_ERROR)
       
   421 	{
       
   422 		if (hResult == -1)
       
   423 			hResult = GetLastError();
       
   424 		szError[0] = 0;
       
   425 		vciFormatError(hResult, szError, sizeof(szError));
       
   426 		printf("Error Establishing CAN channel, Error Code: %s\n",szError); 
       
   427 	}
       
   428    }