00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00068 #include <sys/types.h>
00069 #include <sys/ioctl.h>
00070 #include <net/if.h>
00071 #include <sys/socket.h>
00072 #include <unistd.h>
00073 #include <sys/time.h>
00074 #include <arpa/inet.h>
00075 #include <stdio.h>
00076 #include <fcntl.h>
00077 #include <string.h>
00078 #include <netpacket/packet.h>
00079 #include <pthread.h>
00080 #include <stdlib.h>
00081
00082 #include <youbot_driver/soem/ethercattype.h>
00083 #include <youbot_driver/soem/nicdrv.h>
00084
00086 enum
00087 {
00089 ECT_RED_NONE,
00091 ECT_RED_DOUBLE
00092 };
00093
00095 typedef struct
00096 {
00098 int *sock;
00100 ec_bufT (*txbuf)[EC_MAXBUF];
00102 int (*txbuflength)[EC_MAXBUF];
00104 ec_bufT *tempbuf;
00106 ec_bufT (*rxbuf)[EC_MAXBUF];
00108 int (*rxbufstat)[EC_MAXBUF];
00110 int (*rxsa)[EC_MAXBUF];
00111 } ec_stackT;
00112
00114 ec_bufT ec_rxbuf[EC_MAXBUF];
00116 int ec_rxbufstat[EC_MAXBUF];
00118 static int ec_rxsa[EC_MAXBUF];
00120 static ec_bufT ec_tempinbuf;
00122 static int ec_tempinbufs;
00123
00125 static ec_bufT ec_rxbuf2[EC_MAXBUF];
00127 static int ec_rxbufstat2[EC_MAXBUF];
00129 static int ec_rxsa2[EC_MAXBUF];
00131 static ec_bufT ec_tempinbuf2;
00132
00134 ec_bufT ec_txbuf[EC_MAXBUF];
00136 int ec_txbuflength[EC_MAXBUF];
00138 ec_bufT ec_txbuf2;
00140 int ec_txbuflength2;
00141
00143 int sockhandle = -1;
00145 int sockhandle2 = -1;
00146
00148 static ec_stackT ec_stack[2] = { {&sockhandle, &ec_txbuf, &ec_txbuflength, &ec_tempinbuf, &ec_rxbuf, &ec_rxbufstat,
00149 &ec_rxsa},
00150 {&sockhandle2, &ec_txbuf, &ec_txbuflength, &ec_tempinbuf2, &ec_rxbuf2, &ec_rxbufstat2,
00151 &ec_rxsa2}};
00152
00154 static uint8 ec_lastidx;
00156 int ec_incnt;
00158 int ec_errcnt;
00160 int ec_redstate;
00161
00163 int hlp_txtime;
00165 int hlp_rxtime;
00172 const uint16 priMAC[3] = {0x0101, 0x0101, 0x0101};
00174 const uint16 secMAC[3] = {0x0404, 0x0404, 0x0404};
00175
00177 #define RX_PRIM priMAC[1]
00178
00179 #define RX_SEC secMAC[1]
00180
00181 pthread_mutex_t ec_getindex_mutex = PTHREAD_MUTEX_INITIALIZER;
00182 pthread_mutex_t ec_tx_mutex = PTHREAD_MUTEX_INITIALIZER;
00183 pthread_mutex_t ec_rx_mutex = PTHREAD_MUTEX_INITIALIZER;
00184
00190 int ec_setupnic(const char * ifname, int secondary)
00191 {
00192 int i;
00193 int r, rval, ifindex;
00194 struct timeval timeout;
00195 struct ifreq ifr;
00196 struct sockaddr_ll sll;
00197 int *psock;
00198
00199 rval = 0;
00200 if (secondary)
00201 {
00202
00203 psock = &sockhandle2;
00204 ec_redstate = ECT_RED_DOUBLE;
00205 }
00206 else
00207 {
00208 psock = &sockhandle;
00209 ec_redstate = ECT_RED_NONE;
00210 }
00211
00212 *psock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ECAT));
00213 timeout.tv_sec = 0;
00214 timeout.tv_usec = 1;
00215
00216 r = setsockopt(*psock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
00217 r = setsockopt(*psock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
00218 i = 1;
00219 r = setsockopt(*psock, SOL_SOCKET, SO_DONTROUTE, &i, sizeof(i));
00220
00221 strcpy(ifr.ifr_name, ifname);
00222 r = ioctl(*psock, SIOCGIFINDEX, &ifr);
00223 ifindex = ifr.ifr_ifindex;
00224 strcpy(ifr.ifr_name, ifname);
00225 ifr.ifr_flags = 0;
00226
00227 r = ioctl(*psock, SIOCGIFFLAGS, &ifr);
00228
00229 ifr.ifr_flags = ifr.ifr_flags || IFF_PROMISC || IFF_BROADCAST;
00230 r = ioctl(*psock, SIOCGIFFLAGS, &ifr);
00231
00232 sll.sll_family = AF_PACKET;
00233 sll.sll_ifindex = ifindex;
00234 sll.sll_protocol = htons(ETH_P_ECAT);
00235 r = bind(*psock, (struct sockaddr *)&sll, sizeof(sll));
00236
00237 fcntl(*psock, F_GETFL, 0);
00238
00239
00240
00241 for (i = 0; i < EC_MAXBUF; i++)
00242 {
00243 ec_setupheader(&ec_txbuf[i]);
00244 ec_rxbufstat[i] = EC_BUF_EMPTY;
00245 }
00246 ec_setupheader(&ec_txbuf2);
00247 ec_errcnt = ec_incnt = 0;
00248 if (r == 0)
00249 rval = 1;
00250
00251 return rval;
00252 }
00253
00257 int ec_closenic(void)
00258 {
00259 if (sockhandle >= 0)
00260 close(sockhandle);
00261 if (sockhandle2 >= 0)
00262 close(sockhandle2);
00263
00264 return 0;
00265 }
00266
00272 void ec_setupheader(void *p)
00273 {
00274 ec_etherheadert *bp;
00275 bp = p;
00276 bp->da0 = htons(0xffff);
00277 bp->da1 = htons(0xffff);
00278 bp->da2 = htons(0xffff);
00279 bp->sa0 = htons(priMAC[0]);
00280 bp->sa1 = htons(priMAC[1]);
00281 bp->sa2 = htons(priMAC[2]);
00282 bp->etype = htons(ETH_P_ECAT);
00283 }
00284
00288 uint8 ec_getindex(void)
00289 {
00290 uint8 idx;
00291 int cnt;
00292
00293 pthread_mutex_lock(&ec_getindex_mutex);
00294
00295 idx = ec_lastidx + 1;
00296
00297 if (idx >= EC_MAXBUF)
00298 {
00299 idx = 0;
00300 }
00301 cnt = 0;
00302
00303 while ((ec_rxbufstat[idx] != EC_BUF_EMPTY) && (cnt < EC_MAXBUF))
00304 {
00305 idx++;
00306 cnt++;
00307 if (idx >= EC_MAXBUF)
00308 {
00309 idx = 0;
00310 }
00311 }
00312 ec_rxbufstat[idx] = EC_BUF_ALLOC;
00313 ec_rxbufstat2[idx] = EC_BUF_ALLOC;
00314 ec_lastidx = idx;
00315
00316 pthread_mutex_unlock(&ec_getindex_mutex);
00317
00318 return idx;
00319 }
00320
00325 void ec_setbufstat(uint8 idx, int bufstat)
00326 {
00327 ec_rxbufstat[idx] = bufstat;
00328 ec_rxbufstat2[idx] = bufstat;
00329 }
00330
00336 int ec_outframe(uint8 idx, int stacknumber)
00337 {
00338 int lp, rval;
00339 ec_stackT *stack;
00340
00341 stack = &ec_stack[stacknumber];
00342 lp = (*stack->txbuflength)[idx];
00343 rval = send(*stack->sock, (*stack->txbuf)[idx], lp, 0);
00344 (*stack->rxbufstat)[idx] = EC_BUF_TX;
00345
00346 return rval;
00347 }
00348
00353 int ec_outframe_red(uint8 idx)
00354 {
00355 ec_comt *datagramP;
00356 ec_etherheadert *ehp;
00357 int rval;
00358
00359 ehp = (ec_etherheadert *)&ec_txbuf[idx];
00360
00361 ehp->sa1 = htons(priMAC[1]);
00362
00363 rval = ec_outframe(idx, 0);
00364 if (ec_redstate != ECT_RED_NONE)
00365 {
00366 pthread_mutex_lock(&ec_tx_mutex);
00367 ehp = (ec_etherheadert *)&ec_txbuf2;
00368
00369 datagramP = (ec_comt*)&ec_txbuf2[ETH_HEADERSIZE];
00370
00371 datagramP->index = idx;
00372
00373 ehp->sa1 = htons(secMAC[1]);
00374
00375 send(sockhandle2, &ec_txbuf2, ec_txbuflength2, 0);
00376 pthread_mutex_unlock(&ec_tx_mutex);
00377 ec_rxbufstat2[idx] = EC_BUF_TX;
00378 }
00379
00380 return rval;
00381 }
00382
00387 static int ec_recvpkt(int stacknumber)
00388 {
00389 int lp, bytesrx;
00390 ec_stackT *stack;
00391
00392 stack = &ec_stack[stacknumber];
00393 lp = sizeof(ec_tempinbuf);
00394 bytesrx = recv(*stack->sock, (*stack->tempbuf), lp, 0);
00395 ec_tempinbufs = bytesrx;
00396
00397 return (bytesrx > 0);
00398 }
00399
00415 int ec_inframe(uint8 idx, int stacknumber)
00416 {
00417 uint16 l;
00418 int rval;
00419 uint8 idxf;
00420 ec_etherheadert *ehp;
00421 ec_comt *ecp;
00422 ec_stackT *stack;
00423 ec_bufT *rxbuf;
00424
00425 stack = &ec_stack[stacknumber];
00426 rval = EC_NOFRAME;
00427 rxbuf = &(*stack->rxbuf)[idx];
00428
00429 if ((idx < EC_MAXBUF) && ((*stack->rxbufstat)[idx] == EC_BUF_RCVD))
00430 {
00431 l = (*rxbuf)[0] + ((uint16)((*rxbuf)[1] & 0x0f) << 8);
00432
00433 rval = ((*rxbuf)[l] + ((uint16)(*rxbuf)[l + 1] << 8));
00434
00435 (*stack->rxbufstat)[idx] = EC_BUF_COMPLETE;
00436 }
00437 else
00438 {
00439 pthread_mutex_lock(&ec_rx_mutex);
00440
00441 if (ec_recvpkt(stacknumber))
00442 {
00443 rval = EC_OTHERFRAME;
00444 ehp = (ec_etherheadert*)(stack->tempbuf);
00445
00446 if (ehp->etype == htons(ETH_P_ECAT))
00447 {
00448 ec_incnt++;
00449 ecp = (ec_comt*)(&(*stack->tempbuf)[ETH_HEADERSIZE]);
00450 l = etohs(ecp->elength) & 0x0fff;
00451 idxf = ecp->index;
00452
00453 if (idxf == idx)
00454 {
00455
00456 memcpy(rxbuf, &(*stack->tempbuf)[ETH_HEADERSIZE], (*stack->txbuflength)[idx] - ETH_HEADERSIZE);
00457
00458 rval = ((*rxbuf)[l] + ((uint16)((*rxbuf)[l + 1]) << 8));
00459
00460 (*stack->rxbufstat)[idx] = EC_BUF_COMPLETE;
00461
00462 (*stack->rxsa)[idx] = ntohs(ehp->sa1);
00463 }
00464 else
00465 {
00466 int size = (*stack->txbuflength)[idxf] - ETH_HEADERSIZE;
00467
00468 if (idxf < EC_MAXBUF && size > 0)
00469 {
00470 rxbuf = &(*stack->rxbuf)[idxf];
00471
00472 memcpy(rxbuf, &(*stack->tempbuf)[ETH_HEADERSIZE], (*stack->txbuflength)[idxf] - ETH_HEADERSIZE);
00473
00474 (*stack->rxbufstat)[idxf] = EC_BUF_RCVD;
00475 (*stack->rxsa)[idxf] = ntohs(ehp->sa1);
00476 }
00477 else
00478 {
00479
00480 ec_errcnt++;
00481 printf("There is a other instance of a EtherCAT master running!\n");
00482 exit(0);
00483 }
00484 }
00485 }
00486 }
00487 pthread_mutex_unlock(&ec_rx_mutex);
00488
00489 }
00490
00491
00492 return rval;
00493 }
00494
00506 static int ec_waitinframe_red(uint8 idx, struct timeval tvs)
00507 {
00508 struct timeval tv1, tv2;
00509 int wkc = EC_NOFRAME;
00510 int wkc2 = EC_NOFRAME;
00511 int primrx, secrx;
00512
00513
00514 if (ec_redstate == ECT_RED_NONE)
00515 wkc2 = 0;
00516 do
00517 {
00518
00519 if (wkc <= EC_NOFRAME)
00520 wkc = ec_inframe(idx, 0);
00521
00522 if (ec_redstate != ECT_RED_NONE)
00523 {
00524
00525 if (wkc2 <= EC_NOFRAME)
00526 wkc2 = ec_inframe(idx, 1);
00527 }
00528 gettimeofday(&tv1, 0);
00529
00530 } while (((wkc <= EC_NOFRAME) || (wkc2 <= EC_NOFRAME)) && (timercmp(&tv1, &tvs, <)));
00531
00532 if (ec_redstate != ECT_RED_NONE)
00533 {
00534
00535 primrx = 0;
00536 if (wkc > EC_NOFRAME)
00537 primrx = ec_rxsa[idx];
00538
00539 secrx = 0;
00540 if (wkc2 > EC_NOFRAME)
00541 secrx = ec_rxsa2[idx];
00542
00543
00544
00545 if (((primrx == RX_SEC) && (secrx == RX_PRIM)) )
00546 {
00547
00548 memcpy(&ec_rxbuf[idx], &ec_rxbuf2[idx], ec_txbuflength[idx] - ETH_HEADERSIZE);
00549 wkc = wkc2;
00550 }
00551
00552
00553 if (((primrx == 0) && (secrx == RX_SEC)) ||
00554 ((primrx == RX_PRIM) && (secrx == RX_SEC)) )
00555 {
00556
00557
00558
00559 if ( (primrx == RX_PRIM) && (secrx == RX_SEC) )
00560 {
00561
00562 memcpy(&ec_txbuf[idx][ETH_HEADERSIZE], &ec_rxbuf[idx], ec_txbuflength[idx] - ETH_HEADERSIZE);
00563 }
00564 gettimeofday(&tv1, 0);
00565 tv2.tv_sec = 0;
00566 tv2.tv_usec = EC_TIMEOUTRET;
00567 timeradd(&tv1, &tv2, &tvs);
00568
00569 ec_outframe(idx,1);
00570 do
00571 {
00572
00573 wkc2 = ec_inframe(idx, 1);
00574 gettimeofday(&tv1, 0);
00575 }while ((wkc2 <= EC_NOFRAME) && (timercmp(&tv1, &tvs, <)));
00576 if (wkc2 > EC_NOFRAME)
00577 {
00578
00579 memcpy(&ec_rxbuf[idx], &ec_rxbuf2[idx], ec_txbuflength[idx] - ETH_HEADERSIZE);
00580 wkc = wkc2;
00581 }
00582 }
00583 }
00584
00585
00586 return wkc;
00587 }
00588
00595 int ec_waitinframe(uint8 idx, int timeout)
00596 {
00597 int wkc;
00598 struct timeval tv1, tv2, tve;
00599
00600 gettimeofday(&tv1, 0);
00601 tv2.tv_sec = 0;
00602 tv2.tv_usec = timeout;
00603 timeradd(&tv1, &tv2, &tve);
00604 wkc = ec_waitinframe_red(idx, tve);
00605
00606 if (wkc <= EC_NOFRAME)
00607 {
00608 ec_setbufstat(idx, EC_BUF_EMPTY);
00609 }
00610
00611 return wkc;
00612 }
00613
00625 int ec_srconfirm(uint8 idx, int timeout)
00626 {
00627 int wkc = EC_NOFRAME;
00628 struct timeval tv1, tv2, tv3, tve, tvs, tvh;
00629
00630 gettimeofday(&tv1, 0);
00631 tv2.tv_sec = 0;
00632 tv2.tv_usec = timeout;
00633 timeradd(&tv1, &tv2, &tve);
00634 do
00635 {
00636
00637 ec_outframe_red(idx);
00638 gettimeofday(&tv2, 0);
00639 timersub(&tv2, &tv1, &tvh);
00640 hlp_txtime += (int)tvh.tv_usec;
00641 tv1.tv_sec = 0;
00642 if (timeout < EC_TIMEOUTRET)
00643 {
00644 tv1.tv_usec = timeout;
00645 }
00646 else
00647 {
00648
00649 tv1.tv_usec = EC_TIMEOUTRET;
00650 }
00651 timeradd(&tv2, &tv1, &tvs);
00652
00653 wkc = ec_waitinframe_red(idx, tvs);
00654 gettimeofday(&tv3, 0);
00655 timersub(&tv3, &tv2, &tvh);
00656 hlp_rxtime += (int)tvh.tv_usec;
00657
00658 } while ((wkc <= EC_NOFRAME) && (timercmp(&tv3, &tve, <)));
00659
00660 if (wkc <= EC_NOFRAME)
00661 {
00662 ec_setbufstat(idx, EC_BUF_EMPTY);
00663 }
00664
00665 return wkc;
00666 }