iCub-main
Loading...
Searching...
No Matches
SocketCan.cpp
Go to the documentation of this file.
1// -*- Mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-
2
3/*
4 * Copyright (C) 2010 RobotCub Consortium, European Commission FP6 Project IST-004370
5 * Author: Marco Randazzo
6 * email: marco.randazzo@iit.it
7 * website: www.robotcub.org
8 * Permission is granted to copy, distribute, and/or modify this program
9 * under the terms of the GNU General Public License, version 2 or any
10 * later version published by the Free Software Foundation.
11 *
12 * A copy of the license can be found at
13 * http://www.robotcub.org/icub/license/gpl.txt
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
18 * Public License for more details
19*/
20
24
25#include "SocketCan.h"
26#include <yarp/dev/CanBusInterface.h>
27#include <yarp/os/Bottle.h>
28#include <yarp/os/Value.h>
29#include <sys/types.h>
30#include <yarp/os/Time.h>
31#include <sys/socket.h>
32#include <sys/ioctl.h>
33#include <net/if.h>
34#include <arpa/inet.h>
35#include <linux/can.h>
36#include <linux/can/raw.h>
37#include <sys/ioctl.h>
38#include <string.h>
39#include <stdio.h>
40#include <unistd.h>
41#include <fcntl.h>
42
43
44/* At time of writing, these constants are not defined in the headers */
45#ifndef PF_CAN
46#define PF_CAN 29
47#endif
48
49#ifndef AF_CAN
50#define AF_CAN PF_CAN
51#endif
52
53#define SOCK_DEBUG 0
54
55using namespace yarp::dev;
56using namespace yarp::os;
57
58const int TX_QUEUE_SIZE=2047;
59const int RX_QUEUE_SIZE=2047;
60
62{
63 skt = 0;
64}
65
70
71bool SocketCan::canSetBaudRate(unsigned int rate)
72{
73 //not yet implemented
74 return true;
75}
76
77bool SocketCan::canGetBaudRate(unsigned int *rate)
78{
79 //not yet implemented
80 return true;
81}
82
83bool SocketCan::canIdAdd(unsigned int id)
84{
85 //not yet implemented
86 return true;
87}
88
89bool SocketCan::canIdDelete(unsigned int id)
90{
91 //not yet implemented
92 return true;
93}
94
95bool SocketCan::canRead(CanBuffer &msgs,
96 unsigned int size,
97 unsigned int *readout,
98 bool wait)
99{
100/*
101 int res;
102 #ifdef WIN32
103 long lRead=size;
104 #else
105 int32_t lRead=size;
106 #endif
107
108 CMSG *tmp=reinterpret_cast<CMSG *>(msgs[0].getPointer());
109 if (wait)
110 res=::canRead(*handle, tmp, &lRead, 0);
111 else
112 res=::canTake(*handle, tmp, &lRead);
113
114 *readout=lRead;
115
116 if ( (res==NTCAN_SUCCESS)||(res==NTCAN_RX_TIMEOUT))
117 return true;
118
119 fprintf(stderr, "Error: canRead returned with code:%.8X\n", res);*/
120
121 int i=0;
122 int bytes_read=0;
123 #if SOCK_DEBUG
124 printf("Asked for %d messages\n", size);
125 #endif
126 for (i=0; i<size; i++)
127 {
128 can_frame *frm=reinterpret_cast<can_frame *>(msgs[i].getPointer());
129 //printf("start reading\n");
130 bytes_read = 0;
131 bytes_read = read( skt, frm, sizeof(*frm) );
132 #if SOCK_DEBUG
133 printf("finished reading. read %d bytes\n",bytes_read);
134 #endif
135 if (bytes_read<=0) break;
136
137 #if SOCK_DEBUG
138 printf("Read: %d \n ",bytes_read);
139 printf("len %d ", frm->can_dlc);
140 printf("id %d ", frm->can_id);
141 printf("data: ");
142 for(int j=0;j<frm->can_dlc;j++)
143 printf("%2x ", frm->data[j]);
144 printf("\n");
145 #endif
146
147 //yarp::os::Time::delay(0.010); //test only
148 }
149 *readout=i;
150 #if SOCK_DEBUG
151 printf("Read %d messages\n", *readout);
152 #endif
153 return true;
154
155 /*
156 //debug
157 //struct can_frame frame;
158 can_frame *frame=reinterpret_cast<can_frame *>(msgs[0].getPointer());
159 bytes_read = read( skt, frame, sizeof(*frame) );
160 *readout=1;
161
162 printf("Read: %d \n ",bytes_read);
163
164 printf("len %d ", frame->can_dlc);
165 printf("id %d ", frame->can_id);
166 printf("data: ");
167 for(i=0;i<frame->can_dlc;i++)
168 printf("%2x ", frame->data[i]);
169 printf("\n");
170
171 return true;
172 */
173}
174
175bool SocketCan::canWrite(const CanBuffer &msgs,
176 unsigned int size,
177 unsigned int *sent,
178 bool wait)
179{
180 int res;
181 int32_t lRead=size;
182 int bytes_sent=0;
183
184/*
185 //debug
186 struct can_frame frame2;
187 frame2.can_id = 0x123;
188 strcpy( (char*)(&frame2.data), "YAY" );
189 frame2.can_dlc = strlen( (char*)(&frame2.data) );
190 bytes_sent = write( skt, &frame2, sizeof(frame2) );
191*/
192/*
193 //debug
194 can_frame frame3;
195 frame3.can_id = 0x123;
196 frame3.data[0] = 'Y';
197 frame3.can_dlc = 1;
198 bytes_sent = write( skt, &frame3, sizeof(frame3) );
199*/
200
201 //debug
202 //fprintf(stderr, "id:%d data:%d size:%d\n", tmp->can_id, tmp->data[0], tmp->can_dlc );
203
204 //@@@ IMPORTANT (RANDAZ): I'm putting here a delay of one millisecond.
205 //I noticed that without this delay a lot CAN messages are lost when iCubInterface starts and
206 //sends the configuration parameters (PIDs etc.) to the control boards.
207 //Further investigation is required in order to understand how the internal buffer is handled
208 //when the function write( skt, tmp, sizeof(*tmp) ); is called.
209 Time::delay(0.001);
210
211 int i=0;
212 (*sent)=0;
213 for (i=0; i<size; i++)
214 {
215 CanBuffer &buffer=const_cast<CanBuffer &>(msgs);
216 const struct can_frame *tmp=reinterpret_cast<const struct can_frame*>(buffer[i].getPointer());
217 bytes_sent = write( skt, tmp, sizeof(*tmp) );
218 if (bytes_sent>0)
219 {
220 (*sent)++;
221 }
222 else
223 {
224 fprintf(stderr, "Error: SocketCan::canWrite() was unable to send message.\n");
225 //break;
226 }
227 }
228
229 if (*sent <size)
230 {
231 fprintf(stderr, "Error: SocketCan::canWrite() not all messages were sent.\n");
232 return false;
233 }
234
235 return true;
236}
237
238bool SocketCan::open(yarp::os::Searchable &par)
239{
240 int canTxQueue=TX_QUEUE_SIZE;
241 int canRxQueue=RX_QUEUE_SIZE;
242 int netId =-1;
243 int txTimeout=500;
244 int rxTimeout=500;
245
246 netId=par.check("CanDeviceNum", Value(-1), "numeric identifier of the can device").asInt32();
247 if (netId == -1) netId=par.check("canDeviceNum", Value(-1), "numeric identifier of the can device").asInt32();
248
249 txTimeout=par.check("CanTxTimeout", Value(500), "timeout on transmission [ms]").asInt32();
250 if (txTimeout == 500) txTimeout=par.check("canTxTimeout", Value(500), "timeout on transmission [ms]").asInt32();
251
252 rxTimeout=par.check("CanRxTimeout", Value(500), "timeout on receive when calling blocking read [ms]").asInt32() ;
253 if (rxTimeout == 500) rxTimeout=par.check("canRxTimeout", Value(500), "timeout on receive when calling blocking read [ms]").asInt32() ;
254
255 canTxQueue=par.check("CanTxQueue", Value(TX_QUEUE_SIZE), "length of tx buffer").asInt32();
256 if (canTxQueue == TX_QUEUE_SIZE) canTxQueue=par.check("canTxQueue", Value(TX_QUEUE_SIZE), "length of tx buffer").asInt32();
257
258 canRxQueue=par.check("CanRxQueue", Value(RX_QUEUE_SIZE), "length of rx buffer").asInt32() ;
259 if (canRxQueue == RX_QUEUE_SIZE) canRxQueue=par.check("canRxQueue", Value(RX_QUEUE_SIZE), "length of rx buffer").asInt32() ;
260
261 int so_timestamping_flags = 0;
262 /* Create the socket */
263 skt = socket( PF_CAN, SOCK_RAW, CAN_RAW );
264
265 /* Locate the interface you wish to use */
266 struct ifreq ifr;
267 sprintf (ifr.ifr_name, "can%d",netId);
268 ioctl(skt, SIOCGIFINDEX, &ifr); // ifr.ifr_ifindex gets filled with that device's index
269
270 /* Select that CAN interface, and bind the socket to it. */
271 struct sockaddr_can addr;
272 addr.can_family = AF_CAN;
273 addr.can_ifindex = ifr.ifr_ifindex;
274 bind( skt, (struct sockaddr*)&addr, sizeof(addr) );
275
276 int flags;
277 if (-1 == (flags = fcntl(skt, F_GETFL, 0))) flags = 0;
278 fcntl(skt, F_SETFL, flags | O_NONBLOCK);
279
280
281 return true;
282}
283
285{
286/*
287 int res;
288 if (!handle)
289 return false;
290
291 res=::canClose (*handle);
292
293 if (res!=NTCAN_SUCCESS)
294 return false;
295
296 delete handle;
297 handle=0;
298*/
299
300 if (!skt)
301 return false;
302
303 //not yet implemented
304 return true;
305}
const int TX_QUEUE_SIZE
Definition EsdCan.cpp:21
const int RX_QUEUE_SIZE
Definition EsdCan.cpp:22
const int TX_QUEUE_SIZE
Definition SocketCan.cpp:58
const int RX_QUEUE_SIZE
Definition SocketCan.cpp:59
#define AF_CAN
Definition SocketCan.cpp:50
#define PF_CAN
Definition SocketCan.cpp:46
virtual bool close()
virtual bool canIdAdd(unsigned int id)
Definition SocketCan.cpp:83
virtual bool canRead(CanBuffer &msgs, unsigned int size, unsigned int *read, bool wait=false)
Definition SocketCan.cpp:95
virtual bool canWrite(const CanBuffer &msgs, unsigned int size, unsigned int *sent, bool wait=false)
virtual bool open(yarp::os::Searchable &par)
virtual bool canIdDelete(unsigned int id)
Definition SocketCan.cpp:89
virtual bool canSetBaudRate(unsigned int rate)
Definition SocketCan.cpp:71
virtual bool canGetBaudRate(unsigned int *rate)
Definition SocketCan.cpp:77
fprintf(fid,'\n')