/** FoE write, blocking. * * @param[in] context = context struct * @param[in] slave = Slave number. * @param[in] filename = Filename of file to write. * @param[in] password = password. * @param[in] psize = Size in bytes of file buffer. * @param[out] p = Pointer to file buffer * @param[in] timeout = Timeout per mailbox cycle in us, standard is EC_TIMEOUTRXM * @return Workcounter from last slave response */ int ecx_FOEwrite(ecx_contextt *context, uint16 slave, char *filename, uint32 password, int psize, void *p, int timeout) { ec_FOEt *FOEp, *aFOEp; int wkc; int32 packetnumber, sendpacket = 0; uint16 fnsize, maxdata; int segmentdata; ec_mbxbuft MbxIn, MbxOut; uint8 cnt; boolean worktodo, dofinalzero; int tsize; ec_clearmbx(&MbxIn); /* Empty slave out mailbox if something is in. Timout set to 0 */ wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, 0); ec_clearmbx(&MbxOut); aFOEp = (ec_FOEt *)&MbxIn; FOEp = (ec_FOEt *)&MbxOut; dofinalzero = FALSE; fnsize = strlen(filename); maxdata = context->slavelist[slave].mbx_l - 12; if (fnsize > maxdata) { fnsize = maxdata; } FOEp->MbxHeader.length = htoes(0x0006 + fnsize); FOEp->MbxHeader.address = htoes(0x0000); FOEp->MbxHeader.priority = 0x00; /* get new mailbox count value, used as session handle */ cnt = ec_nextmbxcnt(context->slavelist[slave].mbx_cnt); context->slavelist[slave].mbx_cnt = cnt; FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */ FOEp->OpCode = ECT_FOE_WRITE; FOEp->Password = htoel(password); /* copy filename in mailbox */ memcpy(&FOEp->FileName[0], filename, fnsize); /* send FoE request to slave */ wkc = ecx_mbxsend(context, slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM); if (wkc > 0) /* succeeded to place mailbox in slave ? */ { do { worktodo = FALSE; /* clean mailboxbuffer */ ec_clearmbx(&MbxIn); /* read slave response */ wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, timeout); if (wkc > 0) /* succeeded to read slave response ? */ { /* slave response should be FoE */ if ((aFOEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_FOE) { switch (aFOEp->OpCode) { case ECT_FOE_ACK: { packetnumber = etohl(aFOEp->PacketNumber); if (packetnumber == sendpacket) { if (context->FOEhook) { context->FOEhook(slave, packetnumber, psize); } tsize = psize; if (tsize > maxdata) { tsize = maxdata; } if(tsize || dofinalzero) { worktodo = TRUE; dofinalzero = FALSE; segmentdata = tsize; psize -= segmentdata; /* if last packet was full size, add a zero size packet as final */ /* EOF is defined as packetsize < full packetsize */ if (!psize && (segmentdata == maxdata)) { dofinalzero = TRUE; } FOEp->MbxHeader.length = htoes(0x0006 + segmentdata); FOEp->MbxHeader.address = htoes(0x0000); FOEp->MbxHeader.priority = 0x00; /* get new mailbox count value */ cnt = ec_nextmbxcnt(context->slavelist[slave].mbx_cnt); context->slavelist[slave].mbx_cnt = cnt; FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */ FOEp->OpCode = ECT_FOE_DATA; sendpacket++; FOEp->PacketNumber = htoel(sendpacket); memcpy(&FOEp->Data[0], p, segmentdata); p = (uint8 *)p + segmentdata; /* send FoE data to slave */ wkc = ecx_mbxsend(context, slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM); if (wkc <= 0) { worktodo = FALSE; } } } else { /* FoE error */ wkc = -EC_ERR_TYPE_FOE_PACKETNUMBER; } break; } case ECT_FOE_BUSY: { /* resend if data has been send before */ /* otherwise ignore */ if (sendpacket) { if (!psize) { dofinalzero = TRUE; } psize += segmentdata; p = (uint8 *)p - segmentdata; --sendpacket; } break; } case ECT_FOE_ERROR: { /* FoE error */ wkc = -EC_ERR_TYPE_FOE_ERROR; break; } default: { /* unexpected mailbox received */ wkc = -EC_ERR_TYPE_PACKET_ERROR; break; } } } else { /* unexpected mailbox received */ wkc = -EC_ERR_TYPE_PACKET_ERROR; } } } while (worktodo); } return wkc; }
/** SoE write, blocking. * * The IDN object of the selected slave and DriveNo is written. If a response * is larger than the mailbox size then the response is segmented. * * @param[in] context = context struct * @param[in] slave = Slave number * @param[in] driveNo = Drive number in slave * @param[in] elementflags = Flags to select what properties of IDN are to be transfered. * @param[in] idn = IDN. * @param[in] psize = Size in bytes of parameter buffer. * @param[out] p = Pointer to parameter buffer * @param[in] timeout = Timeout in us, standard is EC_TIMEOUTRXM * @return Workcounter from last slave response */ int ecx_SoEwrite(ecx_contextt *context, uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int psize, void *p, int timeout) { ec_SoEt *SoEp, *aSoEp; uint16 framedatasize, maxdata; int wkc; uint8 *mp; uint8 *hp; uint16 *errorcode; ec_mbxbuft MbxIn, MbxOut; uint8 cnt; boolean NotLast; ec_clearmbx(&MbxIn); /* Empty slave out mailbox if something is in. Timeout set to 0 */ wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, 0); ec_clearmbx(&MbxOut); aSoEp = (ec_SoEt *)&MbxIn; SoEp = (ec_SoEt *)&MbxOut; SoEp->MbxHeader.address = htoes(0x0000); SoEp->MbxHeader.priority = 0x00; SoEp->opCode = ECT_SOE_WRITEREQ; SoEp->error = 0; SoEp->driveNo = driveNo; SoEp->elementflags = elementflags; hp = p; mp = (uint8 *)&MbxOut + sizeof(ec_SoEt); maxdata = context->slavelist[slave].mbx_l - sizeof(ec_SoEt); NotLast = TRUE; while (NotLast) { framedatasize = psize; NotLast = FALSE; SoEp->idn = htoes(idn); SoEp->incomplete = 0; if (framedatasize > maxdata) { framedatasize = maxdata; /* segmented transfer needed */ NotLast = TRUE; SoEp->incomplete = 1; SoEp->fragmentsleft = psize / maxdata; } SoEp->MbxHeader.length = htoes(sizeof(ec_SoEt) - sizeof(ec_mbxheadert) + framedatasize); /* get new mailbox counter, used for session handle */ cnt = ec_nextmbxcnt(context->slavelist[slave].mbx_cnt); context->slavelist[slave].mbx_cnt = cnt; SoEp->MbxHeader.mbxtype = ECT_MBXT_SOE + (cnt << 4); /* SoE */ /* copy parameter data to mailbox */ memcpy(mp, hp, framedatasize); hp += framedatasize; psize -= framedatasize; /* send SoE request to slave */ wkc = ecx_mbxsend(context, slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM); if (wkc > 0) /* succeeded to place mailbox in slave ? */ { if (!NotLast || !ecx_mbxempty(context, slave, timeout)) { /* clean mailboxbuffer */ ec_clearmbx(&MbxIn); /* read slave response */ wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, timeout); if (wkc > 0) /* succeeded to read slave response ? */ { NotLast = FALSE; /* slave response should be SoE, WriteRes */ if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) && (aSoEp->opCode == ECT_SOE_WRITERES) && (aSoEp->error == 0) && (aSoEp->driveNo == driveNo) && (aSoEp->elementflags == elementflags)) { /* SoE write succeeded */ } /* other slave response */ else { if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) && (aSoEp->opCode == ECT_SOE_READRES) && (aSoEp->error == 1)) { mp = (uint8 *)&MbxIn + (etohs(aSoEp->MbxHeader.length) + sizeof(ec_mbxheadert) - sizeof(uint16)); errorcode = (uint16 *)mp; ecx_SoEerror(context, slave, idn, *errorcode); } else { ecx_packeterror(context, slave, idn, 0, 1); /* Unexpected frame returned */ } wkc = 0; } } else { ecx_packeterror(context, slave, idn, 0, 4); /* no response */ } } } } return wkc; }
/** FoE read, blocking. * * @param[in] context = context struct * @param[in] slave = Slave number. * @param[in] filename = Filename of file to read. * @param[in] password = password. * @param[in,out] psize = Size in bytes of file buffer, returns bytes read from file. * @param[out] p = Pointer to file buffer * @param[in] timeout = Timeout per mailbox cycle in us, standard is EC_TIMEOUTRXM * @return Workcounter from last slave response */ int ecx_FOEread(ecx_contextt *context, uint16 slave, char *filename, uint32 password, int *psize, void *p, int timeout) { ec_FOEt *FOEp, *aFOEp; int wkc; int32 dataread = 0; int32 buffersize, packetnumber, prevpacket = 0; uint16 fnsize, maxdata, segmentdata; ec_mbxbuft MbxIn, MbxOut; uint8 cnt; boolean worktodo; buffersize = *psize; ec_clearmbx(&MbxIn); /* Empty slave out mailbox if something is in. Timout set to 0 */ wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, 0); ec_clearmbx(&MbxOut); aFOEp = (ec_FOEt *)&MbxIn; FOEp = (ec_FOEt *)&MbxOut; fnsize = strlen(filename); maxdata = context->slavelist[slave].mbx_l - 12; if (fnsize > maxdata) { fnsize = maxdata; } FOEp->MbxHeader.length = htoes(0x0006 + fnsize); FOEp->MbxHeader.address = htoes(0x0000); FOEp->MbxHeader.priority = 0x00; /* get new mailbox count value, used as session handle */ cnt = ec_nextmbxcnt(context->slavelist[slave].mbx_cnt); context->slavelist[slave].mbx_cnt = cnt; FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */ FOEp->OpCode = ECT_FOE_READ; FOEp->Password = htoel(password); /* copy filename in mailbox */ memcpy(&FOEp->FileName[0], filename, fnsize); /* send FoE request to slave */ wkc = ecx_mbxsend(context, slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM); if (wkc > 0) /* succeeded to place mailbox in slave ? */ { do { worktodo = FALSE; /* clean mailboxbuffer */ ec_clearmbx(&MbxIn); /* read slave response */ wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, timeout); if (wkc > 0) /* succeeded to read slave response ? */ { /* slave response should be FoE */ if ((aFOEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_FOE) { if(aFOEp->OpCode == ECT_FOE_DATA) { segmentdata = etohs(aFOEp->MbxHeader.length) - 0x0006; packetnumber = etohl(aFOEp->PacketNumber); if ((packetnumber == ++prevpacket) && (dataread + segmentdata <= buffersize)) { memcpy(p, &aFOEp->Data[0], segmentdata); dataread += segmentdata; p = (uint8 *)p + segmentdata; if (segmentdata == maxdata) { worktodo = TRUE; } FOEp->MbxHeader.length = htoes(0x0006); FOEp->MbxHeader.address = htoes(0x0000); FOEp->MbxHeader.priority = 0x00; /* get new mailbox count value */ cnt = ec_nextmbxcnt(context->slavelist[slave].mbx_cnt); context->slavelist[slave].mbx_cnt = cnt; FOEp->MbxHeader.mbxtype = ECT_MBXT_FOE + (cnt << 4); /* FoE */ FOEp->OpCode = ECT_FOE_ACK; FOEp->PacketNumber = htoel(packetnumber); /* send FoE ack to slave */ wkc = ecx_mbxsend(context, slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM); if (wkc <= 0) { worktodo = FALSE; } if (context->FOEhook) { context->FOEhook(slave, packetnumber, dataread); } } else { /* FoE error */ wkc = -EC_ERR_TYPE_FOE_BUF2SMALL; } } else { if(aFOEp->OpCode == ECT_FOE_ERROR) { /* FoE error */ wkc = -EC_ERR_TYPE_FOE_ERROR; } else { /* unexpected mailbox received */ wkc = -EC_ERR_TYPE_PACKET_ERROR; } } } else { /* unexpected mailbox received */ wkc = -EC_ERR_TYPE_PACKET_ERROR; } *psize = dataread; } } while (worktodo); } return wkc; }
/** SoE read, blocking. * * The IDN object of the selected slave and DriveNo is read. If a response * is larger than the mailbox size then the response is segmented. The function * will combine all segments and copy them to the parameter buffer. * * @param[in] context = context struct * @param[in] slave = Slave number * @param[in] driveNo = Drive number in slave * @param[in] elementflags = Flags to select what properties of IDN are to be transfered. * @param[in] idn = IDN. * @param[in,out] psize = Size in bytes of parameter buffer, returns bytes read from SoE. * @param[out] p = Pointer to parameter buffer * @param[in] timeout = Timeout in us, standard is EC_TIMEOUTRXM * @return Workcounter from last slave response */ int ecx_SoEread(ecx_contextt *context, uint16 slave, uint8 driveNo, uint8 elementflags, uint16 idn, int *psize, void *p, int timeout) { ec_SoEt *SoEp, *aSoEp; uint16 totalsize, framedatasize; int wkc; uint8 *bp; uint8 *mp; uint16 *errorcode; ec_mbxbuft MbxIn, MbxOut; uint8 cnt; boolean NotLast; ec_clearmbx(&MbxIn); /* Empty slave out mailbox if something is in. Timeout set to 0 */ wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, 0); ec_clearmbx(&MbxOut); aSoEp = (ec_SoEt *)&MbxIn; SoEp = (ec_SoEt *)&MbxOut; SoEp->MbxHeader.length = htoes(sizeof(ec_SoEt) - sizeof(ec_mbxheadert)); SoEp->MbxHeader.address = htoes(0x0000); SoEp->MbxHeader.priority = 0x00; /* get new mailbox count value, used as session handle */ cnt = ec_nextmbxcnt(context->slavelist[slave].mbx_cnt); context->slavelist[slave].mbx_cnt = cnt; SoEp->MbxHeader.mbxtype = ECT_MBXT_SOE + (cnt << 4); /* SoE */ SoEp->opCode = ECT_SOE_READREQ; SoEp->incomplete = 0; SoEp->error = 0; SoEp->driveNo = driveNo; SoEp->elementflags = elementflags; SoEp->idn = htoes(idn); totalsize = 0; bp = p; mp = (uint8 *)&MbxIn + sizeof(ec_SoEt); NotLast = TRUE; /* send SoE request to slave */ wkc = ecx_mbxsend(context, slave, (ec_mbxbuft *)&MbxOut, EC_TIMEOUTTXM); if (wkc > 0) /* succeeded to place mailbox in slave ? */ { while (NotLast) { /* clean mailboxbuffer */ ec_clearmbx(&MbxIn); /* read slave response */ wkc = ecx_mbxreceive(context, slave, (ec_mbxbuft *)&MbxIn, timeout); if (wkc > 0) /* succeeded to read slave response ? */ { /* slave response should be SoE, ReadRes */ if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) && (aSoEp->opCode == ECT_SOE_READRES) && (aSoEp->error == 0) && (aSoEp->driveNo == driveNo) && (aSoEp->elementflags == elementflags)) { framedatasize = etohs(aSoEp->MbxHeader.length) - sizeof(ec_SoEt) + sizeof(ec_mbxheadert); totalsize += framedatasize; /* Does parameter fit in parameter buffer ? */ if (totalsize <= *psize) { /* copy parameter data in parameter buffer */ memcpy(bp, mp, framedatasize); /* increment buffer pointer */ bp += framedatasize; } else { framedatasize -= totalsize - *psize; totalsize = *psize; /* copy parameter data in parameter buffer */ if (framedatasize > 0) memcpy(bp, mp, framedatasize); } if (!aSoEp->incomplete) { NotLast = FALSE; *psize = totalsize; } } /* other slave response */ else { NotLast = FALSE; if (((aSoEp->MbxHeader.mbxtype & 0x0f) == ECT_MBXT_SOE) && (aSoEp->opCode == ECT_SOE_READRES) && (aSoEp->error == 1)) { mp = (uint8 *)&MbxIn + (etohs(aSoEp->MbxHeader.length) + sizeof(ec_mbxheadert) - sizeof(uint16)); errorcode = (uint16 *)mp; ecx_SoEerror(context, slave, idn, *errorcode); } else { ecx_packeterror(context, slave, idn, 0, 1); /* Unexpected frame returned */ } wkc = 0; } } else { NotLast = FALSE; ecx_packeterror(context, slave, idn, 0, 4); /* no response */ } } } return wkc; }