iCub-main
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 
55 using namespace yarp::dev;
56 using namespace yarp::os;
57 
58 const int TX_QUEUE_SIZE=2047;
59 const int RX_QUEUE_SIZE=2047;
60 
62 {
63  skt = 0;
64 }
65 
67 {
68 
69 }
70 
71 bool SocketCan::canSetBaudRate(unsigned int rate)
72 {
73  //not yet implemented
74  return true;
75 }
76 
77 bool SocketCan::canGetBaudRate(unsigned int *rate)
78 {
79  //not yet implemented
80  return true;
81 }
82 
83 bool SocketCan::canIdAdd(unsigned int id)
84 {
85  //not yet implemented
86  return true;
87 }
88 
89 bool SocketCan::canIdDelete(unsigned int id)
90 {
91  //not yet implemented
92  return true;
93 }
94 
95 bool 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 
175 bool 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 
238 bool 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: 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()
Definition: SocketCan.cpp:284
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)
Definition: SocketCan.cpp:175
virtual bool open(yarp::os::Searchable &par)
Definition: SocketCan.cpp:238
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
bool read(yarp::os::Searchable &cfgtotal, pc104Data &pc104data)
Definition: ethParser.cpp:92
bool write(const std::string filename, const FullRegulation &reg)
fprintf(fid,'\n')