|
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 } |