629
|
1 |
// can_copcican_win32.cpp : Defines the exported functions for the DLL application.
|
|
2 |
//
|
|
3 |
|
|
4 |
|
|
5 |
#include "stdafx.h"
|
|
6 |
|
|
7 |
/*
|
|
8 |
This file is part of CanFestival, a library implementing CanOpen Stack.
|
|
9 |
|
|
10 |
Copyright (C): Cosateq GmbH & Co.KG
|
|
11 |
http://www.cosateq.com/
|
|
12 |
http://www.scale-rt.com/
|
|
13 |
|
|
14 |
See COPYING file for copyrights details.
|
|
15 |
|
|
16 |
This library is free software; you can redistribute it and/or
|
|
17 |
modify it under the terms of the GNU Lesser General Public
|
|
18 |
License as published by the Free Software Foundation; either
|
|
19 |
version 2.1 of the License, or (at your option) any later version.
|
|
20 |
|
|
21 |
This library is distributed in the hope that it will be useful,
|
|
22 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
23 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
24 |
Lesser General Public License for more details.
|
|
25 |
|
|
26 |
You should have received a copy of the GNU Lesser General Public
|
|
27 |
License along with this library; if not, write to the Free Software
|
|
28 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
29 |
*/
|
|
30 |
|
|
31 |
/*
|
|
32 |
CAN driver interface for CO-PCICAN card.
|
|
33 |
*/
|
|
34 |
|
|
35 |
#include <stdio.h>
|
|
36 |
//#include <unistd.h>
|
|
37 |
#include <fcntl.h>
|
|
38 |
|
|
39 |
//#define NEED_PRINT_MESSAGE
|
|
40 |
static int initdone = 0;
|
|
41 |
|
|
42 |
inline void * maskDevID(int devId){ return ((void*)( (devId & 0x0000000F) | 0xC05A0000)); }
|
|
43 |
inline int unmaskDevID(void * Ptr){ return ((int)((int)Ptr & 0x0000000F)); }
|
|
44 |
|
|
45 |
/* at the moment not threadsafe :-( */
|
|
46 |
static unsigned char selectedChannelRx = 1, selectedChannelTx = 1;
|
|
47 |
|
|
48 |
static cosateq::devices::can::co_baudrate_t TranslateBaudRate( char* optarg )
|
|
49 |
{
|
|
50 |
/* values see documentation of CO-PCICAN */
|
|
51 |
if( !strcmp( optarg, "1M" ) ) return cosateq::devices::can::CO_BAUD_1M;
|
|
52 |
if( !strcmp( optarg, "800K" ) ) return cosateq::devices::can::CO_BAUD_800k;
|
|
53 |
if( !strcmp( optarg, "500K" ) ) return cosateq::devices::can::CO_BAUD_500k;
|
|
54 |
if( !strcmp( optarg, "250K" ) ) return cosateq::devices::can::CO_BAUD_250k;
|
|
55 |
if( !strcmp( optarg, "125K" ) ) return cosateq::devices::can::CO_BAUD_125k;
|
|
56 |
if( !strcmp( optarg, "100K" ) ) return cosateq::devices::can::CO_BAUD_100k;
|
|
57 |
if( !strcmp( optarg, "83.3K" ) ) return cosateq::devices::can::CO_BAUD_83k;
|
|
58 |
if( !strcmp( optarg, "10K" ) ) return cosateq::devices::can::CO_BAUD_10k;
|
|
59 |
|
|
60 |
return (cosateq::devices::can::co_baudrate_t)-1;
|
|
61 |
}
|
|
62 |
|
|
63 |
int co_pcican_select_channel( const unsigned char channel, const unsigned int direction )
|
|
64 |
{
|
|
65 |
if( channel >= CHANNELS )
|
|
66 |
{
|
|
67 |
MSG("can_copcican_linux: co_pcican_select_channel(): invalid channel\n");
|
|
68 |
return -1;
|
|
69 |
}
|
|
70 |
|
|
71 |
/* at the moment not threadsafe :-( */
|
|
72 |
switch( direction )
|
|
73 |
{
|
|
74 |
case cosateq::devices::can::CO_CAN_RX: selectedChannelRx = channel;
|
|
75 |
break;
|
|
76 |
case cosateq::devices::can::CO_CAN_TX: selectedChannelTx = channel;
|
|
77 |
break;
|
|
78 |
default: return -1;
|
|
79 |
}
|
|
80 |
|
|
81 |
return 0;
|
|
82 |
}
|
|
83 |
|
|
84 |
int co_pcican_configure_selected_channel( const int fd, s_BOARD *board, const unsigned int direction )
|
|
85 |
{
|
|
86 |
unsigned int selectedChannel;
|
|
87 |
int ret = 0;
|
|
88 |
|
|
89 |
if( fd < 0 )
|
|
90 |
{
|
|
91 |
MSG("can_copcican_linux: co_pcican_configure_selected_channel(): invalid file descriptor\n");
|
|
92 |
return -1;
|
|
93 |
}
|
|
94 |
|
|
95 |
if( board == NULL )
|
|
96 |
{
|
|
97 |
MSG("can_copcican_linux: co_pcican_configure_selected_channel(): board is NULL\n");
|
|
98 |
return -1;
|
|
99 |
}
|
|
100 |
|
|
101 |
if( board->baudrate == NULL )
|
|
102 |
{
|
|
103 |
MSG("can_copcican_linux: co_pcican_configure_selected_channel(): baudrate is NULL\n");
|
|
104 |
return -1;
|
|
105 |
}
|
|
106 |
|
|
107 |
switch( direction )
|
|
108 |
{
|
|
109 |
case cosateq::devices::can::CO_CAN_RX: selectedChannel = selectedChannelRx;
|
|
110 |
break;
|
|
111 |
case cosateq::devices::can::CO_CAN_TX: selectedChannel = selectedChannelTx;
|
|
112 |
break;
|
|
113 |
default: selectedChannel = 0xff;
|
|
114 |
}
|
|
115 |
|
|
116 |
if( selectedChannel >= CHANNELS )
|
|
117 |
{
|
|
118 |
MSG("can_copcican_linux: co_pcican_configure_selected_channel(): invalid channel selected\n");
|
|
119 |
return -1;
|
|
120 |
}
|
|
121 |
|
|
122 |
ret = can_setChannelConfig( TranslateBaudRate( board->baudrate ),0x0,unmaskDevID((void*)fd),selectedChannel);
|
|
123 |
if ( ret != 0 ) {
|
|
124 |
can_enterRunMode(unmaskDevID((void*)fd),selectedChannel/2);
|
|
125 |
return -ret;
|
|
126 |
}else{
|
|
127 |
ret = can_setIrqMode(unmaskDevID((void*)fd),selectedChannel);
|
|
128 |
can_enterRunMode(unmaskDevID((void*)fd),selectedChannel/2);
|
|
129 |
}
|
|
130 |
return ret;
|
|
131 |
}
|
|
132 |
|
|
133 |
/*********functions which permit to communicate with the board****************/
|
|
134 |
|
|
135 |
UNS8 __stdcall canReceive_driver( CAN_HANDLE fd0, Message *m )
|
|
136 |
{
|
|
137 |
cosateq::devices::can::co_can_packet_t p;
|
|
138 |
int ret = 0;
|
|
139 |
|
|
140 |
if ( !m )
|
|
141 |
return 0;
|
|
142 |
|
|
143 |
memset(&p,0,sizeof(cosateq::devices::can::co_can_packet_t));
|
|
144 |
ret = can_receive(&p,unmaskDevID(fd0),selectedChannelRx);
|
|
145 |
//printf("rec: %d\n",ret);
|
|
146 |
if ( ret != 0 )
|
|
147 |
return 1;
|
|
148 |
|
|
149 |
//printf("rec2: %d\n",ret);
|
|
150 |
if ( p.size > 8 )
|
|
151 |
p.size = 8;
|
|
152 |
|
|
153 |
if ( !(p.type & MSG_RTR ) )
|
|
154 |
memcpy(m->data,p.data,p.size);
|
|
155 |
|
|
156 |
m->cob_id = p.id;
|
|
157 |
m->len = p.size;
|
|
158 |
m->rtr = p.type & MSG_RTR;
|
|
159 |
|
|
160 |
return 0;
|
|
161 |
}
|
|
162 |
|
|
163 |
/***************************************************************************/
|
|
164 |
|
|
165 |
UNS8 __stdcall canSend_driver( CAN_HANDLE fd0, Message *m )
|
|
166 |
{
|
|
167 |
cosateq::devices::can::co_can_packet_t p;
|
|
168 |
|
|
169 |
if ( !m )
|
|
170 |
return 0;
|
|
171 |
memset(&p,0,sizeof(cosateq::devices::can::co_can_packet_t));
|
|
172 |
p.id = m->cob_id;
|
|
173 |
p.size = (m->len > 8) ? 8 : m->len;
|
|
174 |
p.type = ( m->rtr ) ? 0x2:0x0;
|
|
175 |
if ( p.id > 0x800 )
|
|
176 |
p.type |= MSG_EXT;
|
|
177 |
memcpy(p.data,m->data,p.size);
|
|
178 |
|
|
179 |
return can_send(&p,unmaskDevID(fd0),selectedChannelTx);
|
|
180 |
}
|
|
181 |
|
|
182 |
|
|
183 |
|
|
184 |
/***************************************************************************/
|
|
185 |
|
|
186 |
UNS8 __stdcall canChangeBaudRate_driver( CAN_HANDLE fd0, char* baud )
|
|
187 |
{
|
|
188 |
UNS8 ret = 0;
|
|
189 |
|
|
190 |
ret = can_enterCfgMode(unmaskDevID(fd0),0);
|
|
191 |
if ( ret != 0)
|
|
192 |
MSG("Enter config mode for Channelpair 0 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
|
|
193 |
ret = can_enterCfgMode(unmaskDevID(fd0),1);
|
|
194 |
if ( ret != 0)
|
|
195 |
MSG("Enter config mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
|
|
196 |
|
|
197 |
for ( int i = 0; i < 4; i++ ) {
|
|
198 |
ret = can_setChannelConfig(TranslateBaudRate(baud),0x0,unmaskDevID(fd0),i);
|
|
199 |
if ( ret != 0)
|
|
200 |
MSG("Set config for channel %d failed in Function %s! Error: %d\n",i,__FUNCTION__,ret);
|
|
201 |
can_setIrqMode(unmaskDevID(fd0),i);
|
|
202 |
}
|
|
203 |
ret = can_enterRunMode(unmaskDevID(fd0),0);
|
|
204 |
if ( ret != 0)
|
|
205 |
MSG("Enter run mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
|
|
206 |
|
|
207 |
ret = can_enterRunMode(unmaskDevID(fd0),1);
|
|
208 |
if ( ret != 0)
|
|
209 |
MSG("Enter run mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
|
|
210 |
|
|
211 |
return ret;
|
|
212 |
}
|
|
213 |
|
|
214 |
CAN_HANDLE __stdcall canOpen_driver( s_BOARD *board )
|
|
215 |
{
|
|
216 |
int ret = 0;
|
|
217 |
int devId = 0;
|
|
218 |
if ( !board )
|
|
219 |
return NULL;
|
|
220 |
if ( !board->busname )
|
|
221 |
return NULL;
|
|
222 |
//TODO find out how boardname resolves
|
|
223 |
|
|
224 |
//printf("BOARD: 0x%x %s\n",board,board->busname);
|
|
225 |
//sscanf_s(board->busname,"%d",&devId);
|
|
226 |
|
|
227 |
if ( devId < 0 || devId > 15 )
|
|
228 |
return NULL;
|
|
229 |
|
|
230 |
//return (can_HANDLE)NULL;
|
|
231 |
if ( !initdone ) {
|
|
232 |
can_init();
|
|
233 |
initdone = 1;
|
|
234 |
}
|
|
235 |
|
|
236 |
ret = can_open(devId);
|
|
237 |
if ( ret < 0 )
|
|
238 |
return (CAN_HANDLE)NULL;
|
|
239 |
|
|
240 |
canChangeBaudRate_driver( maskDevID(devId),board->baudrate );
|
|
241 |
|
|
242 |
return maskDevID(devId);
|
|
243 |
}
|
|
244 |
|
|
245 |
int __stdcall canClose_driver(CAN_HANDLE fd0 )
|
|
246 |
{
|
|
247 |
return can_close(unmaskDevID(fd0));
|
|
248 |
}
|
|
249 |
|