ethercatfoe.c
Go to the documentation of this file.
00001 /*
00002  * Simple Open EtherCAT Master Library 
00003  *
00004  * File    : ethercatfoe.c
00005  * Version : 1.3.0
00006  * Date    : 24-02-2013
00007  * Copyright (C) 2005-2013 Speciaal Machinefabriek Ketels v.o.f.
00008  * Copyright (C) 2005-2013 Arthur Ketels
00009  * Copyright (C) 2008-2009 TU/e Technische Universiteit Eindhoven 
00010  *
00011  * SOEM is free software; you can redistribute it and/or modify it under
00012  * the terms of the GNU General Public License version 2 as published by the Free
00013  * Software Foundation.
00014  *
00015  * SOEM is distributed in the hope that it will be useful, but WITHOUT ANY
00016  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00017  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00018  * for more details.
00019  *
00020  * As a special exception, if other files instantiate templates or use macros
00021  * or inline functions from this file, or you compile this file and link it
00022  * with other works to produce a work based on this file, this file does not
00023  * by itself cause the resulting work to be covered by the GNU General Public
00024  * License. However the source code for this file must still be made available
00025  * in accordance with section (3) of the GNU General Public License.
00026  *
00027  * This exception does not invalidate any other reasons why a work based on
00028  * this file might be covered by the GNU General Public License.
00029  *
00030  * The EtherCAT Technology, the trade name and logo “EtherCAT” are the intellectual
00031  * property of, and protected by Beckhoff Automation GmbH. You can use SOEM for
00032  * the sole purpose of creating, using and/or selling or otherwise distributing
00033  * an EtherCAT network master provided that an EtherCAT Master License is obtained
00034  * from Beckhoff Automation GmbH.
00035  *
00036  * In case you did not receive a copy of the EtherCAT Master License along with
00037  * SOEM write to Beckhoff Automation GmbH, Eiserstraße 5, D-33415 Verl, Germany
00038  * (www.beckhoff.com).
00039  *
00040  * 14-06-2010 : fixed bug in FOEread() by Torsten Bitterlich
00041  */
00042 
00050 #include <stdio.h>
00051 #include <string.h>
00052 #include "ethercat_soem/osal.h"
00053 #include "ethercat_soem/oshw.h"
00054 #include "ethercat_soem/ethercattype.h"
00055 #include "ethercat_soem/ethercatbase.h"
00056 #include "ethercat_soem/ethercatmain.h"
00057 #include "ethercat_soem/ethercatfoe.h"
00058 
00059 #define EC_MAXFOEDATA 512
00060 
00064 PACKED_BEGIN
00065 typedef struct PACKED
00066 {
00067    ec_mbxheadert MbxHeader;
00068    uint8         OpCode;
00069    uint8         Reserved;
00070    union
00071    {   
00072       uint32        Password;
00073       uint32        PacketNumber;
00074       uint32        ErrorCode;
00075    };
00076    union
00077    {   
00078       char          FileName[EC_MAXFOEDATA];
00079       uint8         Data[EC_MAXFOEDATA];
00080       char          ErrorText[EC_MAXFOEDATA];
00081    };   
00082 } ec_FOEt;
00083 PACKED_END
00084 
00091 int ecx_FOEdefinehook(ecx_contextt *context, void *hook)
00092 {
00093   context->FOEhook = hook; 
00094   return 1;
00095 }
00096 
00108 int ecx_FOEread(ecx_contextt *context, uint16 slave, char *filename, uint32 password, int *psize, void *p, int timeout)
00109 {
00110    ec_FOEt *FOEp, *aFOEp;
00111    int wkc;
00112    int32 dataread = 0;
00113    int32 buffersize, packetnumber, prevpacket = 0;
00114    uint16 fnsize, maxdata, segmentdata;
00115    ec_mbxbuft MbxIn, MbxOut;
00116    uint8 cnt;
00117    boolean worktodo;
00118 
00119    buffersize = *psize;
00120    ec_clearmbx(&MbxIn);
00121    /* Empty slave out mailbox if something is in. Timout set to 0 */
00122    wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, 0);
00123    ec_clearmbx(&MbxOut);
00124    aFOEp = (ec_FOEt *)&MbxIn;
00125    FOEp = (ec_FOEt *)&MbxOut;
00126    fnsize = strlen(filename);
00127    maxdata = context->slavelist[slave].mbx_l - 12;
00128    if (fnsize > maxdata)
00129    {
00130       fnsize = maxdata;
00131    }
00132    FOEp->MbxHeader.length = htoes(0x0006 + fnsize);
00133    FOEp->MbxHeader.address = htoes(0x0000);
00134    FOEp->MbxHeader.priority = 0x00;
00135    /* get new mailbox count value, used as session handle */
00136    cnt = ec_nextmbxcnt(context->slavelist[slave].mbx_cnt);
00137    context->slavelist[slave].mbx_cnt = cnt;
00138    FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */
00139    FOEp->OpCode = ECT_FOE_READ;
00140    FOEp->Password = htoel(password);
00141    /* copy filename in mailbox */
00142    memcpy(&FOEp->FileName[0], filename, fnsize);
00143    /* send FoE request to slave */
00144    wkc = ecx_mbxsend(context, slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00145    if (wkc > 0) /* succeeded to place mailbox in slave ? */
00146    {
00147       do
00148       {   
00149          worktodo = FALSE;
00150          /* clean mailboxbuffer */
00151          ec_clearmbx(&MbxIn);
00152          /* read slave response */
00153          wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, timeout);
00154          if (wkc > 0) /* succeeded to read slave response ? */
00155          {
00156             /* slave response should be FoE */
00157             if ((aFOEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_FOE)
00158             {
00159                if(aFOEp->OpCode == ECT_FOE_DATA)
00160                {
00161                   segmentdata = etohs(aFOEp->MbxHeader.length) - 0x0006;
00162                   packetnumber = etohl(aFOEp->PacketNumber);
00163                   if ((packetnumber == ++prevpacket) && (dataread + segmentdata <= buffersize))
00164                   {
00165                      memcpy(p, &aFOEp->Data[0], segmentdata);
00166                      dataread += segmentdata;
00167                      p = (uint8 *)p + segmentdata;
00168                      if (segmentdata == maxdata)
00169                      {
00170                         worktodo = TRUE; 
00171                      }
00172                      FOEp->MbxHeader.length = htoes(0x0006);
00173                      FOEp->MbxHeader.address = htoes(0x0000);
00174                      FOEp->MbxHeader.priority = 0x00;
00175                      /* get new mailbox count value */
00176                      cnt = ec_nextmbxcnt(context->slavelist[slave].mbx_cnt);
00177                      context->slavelist[slave].mbx_cnt = cnt;
00178                      FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */
00179                      FOEp->OpCode = ECT_FOE_ACK;
00180                      FOEp->PacketNumber = htoel(packetnumber);
00181                      /* send FoE ack to slave */
00182                      wkc = ecx_mbxsend(context, slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00183                      if (wkc <= 0)
00184                      {   
00185                         worktodo = FALSE;
00186                      }
00187                      if (context->FOEhook)
00188                      {
00189                         context->FOEhook(slave, packetnumber, dataread);
00190                      }
00191                   }
00192                   else
00193                   {
00194                      /* FoE error */
00195                      wkc = -EC_ERR_TYPE_FOE_BUF2SMALL;
00196                   }
00197                }
00198                else
00199                {
00200                   if(aFOEp->OpCode == ECT_FOE_ERROR)
00201                   {
00202                      /* FoE error */
00203                      wkc = -EC_ERR_TYPE_FOE_ERROR;
00204                   }
00205                   else
00206                   {
00207                      /* unexpected mailbox received */
00208                      wkc = -EC_ERR_TYPE_PACKET_ERROR;
00209                   }
00210                }
00211             }
00212             else
00213             {
00214                /* unexpected mailbox received */
00215                wkc = -EC_ERR_TYPE_PACKET_ERROR;
00216             }
00217             *psize = dataread;
00218          }
00219       } while (worktodo);   
00220    }
00221    
00222    return wkc;
00223 }   
00224 
00236 int ecx_FOEwrite(ecx_contextt *context, uint16 slave, char *filename, uint32 password, int psize, void *p, int timeout)
00237 {
00238    ec_FOEt *FOEp, *aFOEp;
00239    int wkc;
00240    int32 packetnumber, sendpacket = 0;
00241    uint16 fnsize, maxdata;
00242    int segmentdata;
00243    ec_mbxbuft MbxIn, MbxOut;
00244    uint8 cnt;
00245    boolean worktodo, dofinalzero;
00246    int tsize;
00247 
00248    ec_clearmbx(&MbxIn);
00249    /* Empty slave out mailbox if something is in. Timout set to 0 */
00250    wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, 0);
00251    ec_clearmbx(&MbxOut);
00252    aFOEp = (ec_FOEt *)&MbxIn;
00253    FOEp = (ec_FOEt *)&MbxOut;
00254    dofinalzero = FALSE;
00255    fnsize = strlen(filename);
00256    maxdata = context->slavelist[slave].mbx_l - 12;
00257    if (fnsize > maxdata)
00258    {
00259       fnsize = maxdata;
00260    }
00261    FOEp->MbxHeader.length = htoes(0x0006 + fnsize);
00262    FOEp->MbxHeader.address = htoes(0x0000);
00263    FOEp->MbxHeader.priority = 0x00;
00264    /* get new mailbox count value, used as session handle */
00265    cnt = ec_nextmbxcnt(context->slavelist[slave].mbx_cnt);
00266    context->slavelist[slave].mbx_cnt = cnt;
00267    FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */
00268    FOEp->OpCode = ECT_FOE_WRITE;
00269    FOEp->Password = htoel(password);
00270    /* copy filename in mailbox */
00271    memcpy(&FOEp->FileName[0], filename, fnsize);
00272    /* send FoE request to slave */
00273    wkc = ecx_mbxsend(context, slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00274    if (wkc > 0) /* succeeded to place mailbox in slave ? */
00275    {
00276       do
00277       {   
00278          worktodo = FALSE;
00279          /* clean mailboxbuffer */
00280          ec_clearmbx(&MbxIn);
00281          /* read slave response */
00282          wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, timeout);
00283          if (wkc > 0) /* succeeded to read slave response ? */
00284          {
00285             /* slave response should be FoE */
00286             if ((aFOEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_FOE)
00287             {
00288                switch (aFOEp->OpCode)
00289                {
00290                   case ECT_FOE_ACK:
00291                   {
00292                      packetnumber = etohl(aFOEp->PacketNumber);
00293                      if (packetnumber == sendpacket)
00294                      {
00295                         if (context->FOEhook)
00296                         {
00297                            context->FOEhook(slave, packetnumber, psize);
00298                         }
00299                         tsize = psize;
00300                         if (tsize > maxdata)
00301                         {
00302                            tsize = maxdata;
00303                         }
00304                         if(tsize || dofinalzero)
00305                         {
00306                            worktodo = TRUE; 
00307                            dofinalzero = FALSE;
00308                            segmentdata = tsize;
00309                            psize -= segmentdata;
00310                            /* if last packet was full size, add a zero size packet as final */
00311                            /* EOF is defined as packetsize < full packetsize */
00312                            if (!psize && (segmentdata == maxdata))
00313                            {
00314                               dofinalzero = TRUE;
00315                            }
00316                            FOEp->MbxHeader.length = htoes(0x0006 + segmentdata);
00317                            FOEp->MbxHeader.address = htoes(0x0000);
00318                            FOEp->MbxHeader.priority = 0x00;
00319                            /* get new mailbox count value */
00320                            cnt = ec_nextmbxcnt(context->slavelist[slave].mbx_cnt);
00321                            context->slavelist[slave].mbx_cnt = cnt;
00322                            FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */
00323                            FOEp->OpCode = ECT_FOE_DATA;
00324                            sendpacket++;
00325                            FOEp->PacketNumber = htoel(sendpacket);
00326                            memcpy(&FOEp->Data[0], p, segmentdata);
00327                            p = (uint8 *)p + segmentdata;
00328                            /* send FoE data to slave */
00329                            wkc = ecx_mbxsend(context, slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM);
00330                            if (wkc <= 0)
00331                            {   
00332                               worktodo = FALSE;
00333                            }
00334                         }
00335                      }
00336                      else
00337                      {
00338                         /* FoE error */
00339                         wkc = -EC_ERR_TYPE_FOE_PACKETNUMBER;
00340                      }
00341                      break;
00342                   }
00343                   case ECT_FOE_BUSY:
00344                   {
00345                      /* resend if data has been send before */
00346                      /* otherwise ignore */
00347                      if (sendpacket)
00348                      {
00349                         if (!psize)
00350                         {
00351                            dofinalzero = TRUE;
00352                         }
00353                         psize += segmentdata;
00354                         p = (uint8 *)p - segmentdata;
00355                         --sendpacket;
00356                      }
00357                      break;
00358                   }
00359                   case ECT_FOE_ERROR:
00360                   {
00361                      /* FoE error */
00362                      wkc = -EC_ERR_TYPE_FOE_ERROR;
00363                      break;
00364                   }
00365                   default:
00366                   {
00367                      /* unexpected mailbox received */
00368                      wkc = -EC_ERR_TYPE_PACKET_ERROR;
00369                   }
00370                }
00371             }
00372             else
00373             {
00374                /* unexpected mailbox received */
00375                wkc = -EC_ERR_TYPE_PACKET_ERROR;
00376             }
00377          }
00378       } while (worktodo);   
00379    }
00380    
00381    return wkc;
00382 }
00383 
00384 #ifdef EC_VER1
00385 int ec_FOEdefinehook(void *hook)
00386 {
00387    return ecx_FOEdefinehook(&ecx_context, hook);
00388 }
00389 
00390 int ec_FOEread(uint16 slave, char *filename, uint32 password, int *psize, void *p, int timeout)
00391 {
00392    return ecx_FOEread(&ecx_context, slave, filename, password, psize, p, timeout);
00393 }
00394 
00395 int ec_FOEwrite(uint16 slave, char *filename, uint32 password, int psize, void *p, int timeout)
00396 {
00397    return ecx_FOEwrite(&ecx_context, slave, filename, password, psize, p, timeout);
00398 }
00399 #endif


ethercat_soem
Author(s): Arthur Ketels, M.J.G. van de Molengraft
autogenerated on Wed Aug 26 2015 11:32:40