/*-------------------- Backup_Bind_Table_req -------------------- 2.4.3.2.8 Backup_Bind_Table_req. (ClusterID=0x0027) The Backup_Bind_Table_req is generated from a local primary binding table cache and sent to the remote backup binding table cache device to request backup storage of its entire binding table. The destination addressing mode for this request is unicast. IN: The package with the request information. OUT: The size in bytes of the request payload. */ zbSize_t Backup_Bind_Table_req ( zbBackupBindTableRequest_t *pMessageComingIn /* IN: The package with the request information. */ ) { zbSize_t payloadLength; uint8_t *pPtr = NULL; uint16_t cIndex; uint16_t limit; payloadLength = MbrOfs(zbBackupBindTableRequest_t, BindingTableList[0]); pPtr = (uint8_t *)&pMessageComingIn->BindingTableList[0]; limit = OTA2Native16(TwoBytesToUint16(pMessageComingIn->BindingTableListCount)); for (cIndex = 0; cIndex < limit; cIndex++) { if (((zbApsmeBindEntry_t *)pPtr)->dstAddrMode == zbGroupMode) { payloadLength += (MbrOfs(zbApsmeBindEntry_t, dstAddrMode) + sizeof(zbGroupId_t)); pPtr += (MbrOfs(zbApsmeBindEntry_t, dstAddrMode) + sizeof(zbGroupId_t)); } else { payloadLength += sizeof(zbApsmeBindEntry_t); pPtr += sizeof(zbApsmeBindEntry_t); } } return (payloadLength); }
/*-------------------- Remove_Bkup_Bind_Entry_req -------------------- 2.4.3.2.7 Remove_Bkup_Bind_Entry_req. (ClusterID=0x0026) The Remove_Bkup_Bind_Entry_req is generated from a local primary binding table cache and sent to a remote backup binding table cache device to request removal of the entry from backup storage. It will be generated whenever a binding table entry has been unbound by the primary binding table cache. The destination addressing mode for this request is unicast. IN: The package with the request information. OUT: The size in bytes of the request payload. */ zbSize_t Remove_Bkup_Bind_Entry_req ( zbRemoveBackupBindEntryRequest_t *pMessageComingIn /* IN: The package with the request information. */ ) { if (pMessageComingIn->addressMode == zbGroupMode) return (MbrOfs(zbRemoveBackupBindEntryRequest_t, destData) + sizeof(groupMode_t)); else return (MbrOfs(zbRemoveBackupBindEntryRequest_t, destData) + sizeof(extendedMode_t)); }
/*-------------------- Bind_Unbind_req -------------------- 2.4.3.2.2 Bind_req and 2.4.3.2.3 Unbind_req. (ClusterID=0x0021) - (ClusterID=0x0022) Retunrs the proper size in bytes for the Bind_req and Unbind_req primitives. IN: The request package with the message information. OUT: The size in bytes for the request package. */ zbSize_t Bind_Unbind_req ( zbBindUnbindRequest_t *pMessageComingIn /* IN: The request package with the message information. */ ) { if (pMessageComingIn->addressMode == zbGroupMode) return (MbrOfs(zbBindUnbindRequest_t, destData) + sizeof(groupMode_t)); else return (MbrOfs(zbBindUnbindRequest_t, destData) + sizeof(extendedMode_t)); }
/*-------------------- Match_Desc_req -------------------- 2.4.3.1.7 Match_Desc_req. (ClusterID=0x0006) The Match_Desc_req command is generated from a local device wishing to find remote devices supporting a specific simple descriptor match criterion. This command shall either be broadcast to all RxOnWhenIdle devices or unicast. If the command is unicast, it shall be directed either to the remote device itself or to an alternative device that contains the discovery information of the remote device. The local device shall generate the Match_Desc_req command using the format illustrated in Table 2.47. The NWKAddrOfInterest field shall contain the broadcast to all RxOnWhenIdle devices network address (0xfffd), if the command is to be broadcast, or the network address of the remote device for which the match is required. IN: The buffer where the request will be generated. IN: The package with the request data. IN: The Address of the destination node. OUT: The Size of the payload for the request. */ zbSize_t Match_Desc_req ( uint8_t *pkgPayload, /* IN: The buffer where the request will be generated. */ zbMatchDescriptorRequestPtr_t *pMessageComingIn, /* IN: The package with the request data. */ zbNwkAddr_t aDestAddr /* IN: The Address of the destination node. */ ) { zbSize_t payloadLength; FLib_MemCpy(pkgPayload , pMessageComingIn, MbrOfs(zbMatchDescriptorRequestPtr_t, inputClusterList)); payloadLength = MbrOfs(zbMatchDescriptorRequestPtr_t, inputClusterList) + ZDP_CopyClusterListPairToFrame(pkgPayload + MbrOfs(zbMatchDescriptorRequestPtr_t, inputClusterList), (void *)&pMessageComingIn->inputClusterList); Zdp_GenerateDataReq(gMatch_Desc_req_c, aDestAddr, (afToApsdeMessage_t *)(pkgPayload - SapHandlerDataStructureOffSet), payloadLength ); return gZdpAlreadyHanlded_c; }
/*-------------------- End_Device_Bind_req -------------------- 2.4.3.2.1 End_Device_Bind_req. (ClusterID=0x0020) The End_Device_Bind_req is generated from a Local Device wishing to perform End Device Bind with a Remote Device. The End_Device_Bind_req is generated, typically based on some user action like a button press. The destination addressing on this command shall be unicast and the destination address shall be that of the ZigBee Coordinator. IN/OUT: The buffer where the request data will be filled in. IN: The package with the request information. IN: The destination address where to send the request. OUT: The size in bytes of the request payload. */ zbSize_t End_Device_Bind_req ( uint8_t *pkgPayload, /* IN/OUT: The buffer where the request data will be filled in. */ zbEndDeviceBindRequest_t *pMessageComingIn, /* IN: The package with the request information. */ zbNwkAddr_t aDestAddr /* IN: The destination address where to send the request. */ ) { zbSize_t payloadLength; FLib_MemCpy(pkgPayload, pMessageComingIn, MbrOfs(zbEndDeviceBindRequest_t, inputClusterList)); payloadLength = MbrOfs(zbEndDeviceBindRequest_t, inputClusterList) + ZDP_CopyClusterListPairToFrame(pkgPayload + MbrOfs(zbEndDeviceBindRequest_t, inputClusterList), &pMessageComingIn->inputClusterList); Zdp_GenerateDataReq( gEnd_Device_Bind_req_c, aDestAddr, (afToApsdeMessage_t *)(pkgPayload - SapHandlerDataStructureOffSet) , payloadLength ); return gZdpAlreadyHanlded_c; }
uint8_t AppHcZtc_SAPHandler(hcZtcMessage_t *ztcMessage) { OepFragmentedApdu_t* pOepFragmentedApdu = (OepFragmentedApdu_t *)ztcMessage; uint8_t dataLenToCopy; uint8_t dstOffset = MbrOfs(OepFragmentedApdu_t, fragment) + MbrOfs(OepApduFragment_t, data); uint8_t srcOffset = MbrOfs(hcZtcMessage_t, data); if (ztcMessage->msgType >= gHcZtcOpcodeMarker_StartOfCfgRxCmds && ztcMessage->msgType <= gHcZtcOpcodeMarker_EndOfCfgRxCmds) { oepObjCfgFrame_t* pZtcFrame; hcZtcObjCfgFrame_t* pZtcObjCfgFrame; dstOffset += MbrOfs(oepObjCfgFrame_t, frame); srcOffset += MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame); dataLenToCopy = ztcMessage->msgLen - MbrSizeof(hcZtcObjCfgFrame_t, endPoint) - MbrSizeof(hcZtcFrame_t, nextFragmentPresent); /* ZHCTODO support fragmentation */ FLib_MemInPlaceCpy((uint8_t *)ztcMessage + dstOffset, (uint8_t *)ztcMessage + srcOffset, dataLenToCopy); pZtcFrame = (oepObjCfgFrame_t *)pOepFragmentedApdu->fragment.data; pZtcFrame->choice = (gHcZtcObjCfgChoice_HeaderByte << 8) | ztcMessage->msgType; pZtcFrame->apduLen = MbrSizeof(oepObjCfgFrame_t, choice) + dataLenToCopy; pOepFragmentedApdu->fragment.len = pZtcFrame->apduLen + MbrSizeof(oepObjCfgFrame_t, apduLen); pZtcObjCfgFrame = (hcZtcObjCfgFrame_t *)ztcMessage->data; pOepFragmentedApdu->dstEndPoint = pZtcObjCfgFrame->endPoint; /* ZHCTODO support fragmentation */ pOepFragmentedApdu->fragment.nextFragment = NULL; } else { /* ZHCTODO association and prst frames */ } ZCL_Oep_SAPHandler(pOepFragmentedApdu); return gZbSuccess_c; }
/*-------------------- Backup_Source_Bind_req -------------------- 2.4.3.2.10 Backup_Source_Bind_req. (ClusterID=0x0029) The Backup_Source_Bind_req is generated from a local primary binding table cache and sent to a remote backup binding table cache device to request backup storage of its entire source table. The destination addressing mode for this request is unicast. IN: The package with the request information. OUT: The size in bytes of the request payload. */ zbSize_t Backup_Source_Bind_req ( zbBackupSourceBindRequest_t *pMessageComingIn /* IN: The package with the request information. */ ) { return ((MbrOfs(zbBackupSourceBindRequest_t, SourceTableList[0]) + (MbrSizeof(zbBackupSourceBindRequest_t, SourceTableList[0]) * OTA2Native16(TwoBytesToUint16(pMessageComingIn->SourceTableListCount))))); }
/*-------------------- Active_EP_store_req -------------------- 2.4.3.1.17 Active_EP_store_req. (ClusterID=0x0019) The Active_EP_store_req is provided to enable ZigBee end devices on the network to request storage of their list of Active Endpoints on a Primary Discovery Cache device which has previously received a SUCCESS status from a Discovery_store_req to the same Primary Discovery Cache device. Included in this request is the count of Active Endpoints the Local Device wishes to cache and the endpoint list itself. IN/OUT: The destination address where to send the request. IN: The package with the request information. OUT: The size in bytes of the request payload. */ zbSize_t Active_EP_store_req ( zbNwkAddr_t aAddress, /* IN/OUT: The destination address where to send the request. */ zbActiveEPStoreRequest_t *pMessageGoingOut /* IN: The package with the request information. */ ) { if (gDiscoveryCacheResponse) Copy2Bytes(aAddress, gDiscoveryCacheSuccess.aNwkAddress); return (MbrOfs(zbActiveEPStoreRequest_t, activeEPList[0]) + pMessageGoingOut->activeEPCount); }
/*-------------------- Simple_Desc_store_req -------------------- 2.4.3.1.18 Simple_Desc_store_req. (ClusterID=0x001a) The Simple_desc_store_req is provided to enable ZigBee end devices on the network to request storage of their list of Simple Descriptors on a Primary Discovery Cache device which has previously received a SUCCESS status from a Discovery_store_req to the same Primary Discovery Cache device. Note that each Simple Descriptor for every active endpoint on the Local Device must be individually uploaded to the Primary Discovery Cache device via this command to enable cached discovery. Included in this request is the length of the Simple Descriptor the Local Device wishes to cache and the Simple Descriptor itself. The endpoint is a field within the Simple Descriptor and is accessed by the Remote Device to manage the discovery cache information for the Local Device. IN/OUT: The buffer where the request data will be filled in. IN: The package with the request information. IN: The destination address where to send the request. OUT: The size in bytes of the request payload. */ zbSize_t Simple_Desc_store_req ( uint8_t *pkgPayload, /* IN/OUT: The buffer where the request data will be filled in. */ zbSimpleDescriptorStoreRequest_t *pMessageComingIn, /* IN: The package with the request information. */ zbNwkAddr_t aDestAddr /* IN: The destination address where to send the request. */ ) { zbSize_t payloadLength; if (gDiscoveryCacheResponse) Copy2Bytes(aDestAddr, gDiscoveryCacheSuccess.aNwkAddress); FLib_MemCpy(pkgPayload, pMessageComingIn,MbrOfs(zbSimpleDescriptorStoreRequest_t, simpleDescriptor.inputClusters)); payloadLength = MbrOfs(zbSimpleDescriptorStoreRequest_t, simpleDescriptor.inputClusters) + ZDP_CopyClusterListPairToFrame(pkgPayload + MbrOfs(zbSimpleDescriptorStoreRequest_t, simpleDescriptor.inputClusters), &(pMessageComingIn->simpleDescriptor.inputClusters)); Zdp_GenerateDataReq(gSimple_Desc_store_req_c, aDestAddr, (afToApsdeMessage_t *)(pkgPayload - SapHandlerDataStructureOffSet) , payloadLength ); return gZdpAlreadyHanlded_c; }
zbSize_t Mgmt_NWK_Update_notify ( zbMgmtNwkUpdateNotify_t *pRequest ) { zbSize_t size = MbrOfs(zbMgmtNwkUpdateNotify_t, aEnergyValues); if (ZdoGetNwkManagerBitMask(gaServerMask)) { (void) pRequest; (void) size; return gZero_c; } return (size + (pRequest->ScannedChannelsListCount /* *MbrSizeof(zbMgmtNwkUpdateNotify_t, aEnergyValues)*/)); }
/*-------------------- User_Desc_set -------------------- 2.4.3.1.12 User_Desc_set. (ClusterID=0x0014) The User_Desc_set command is generated from a local device wishing to configure the user descriptor on a remote device. This command shall be unicast either to the remote device itself or to an alternative device that contains the discovery information of the remote device. The local device shall generate the User_Desc_set command using the format illustrated in Table 2.52. The NWKAddrOfInterest field shall contain the network address of the remote device for which the user descriptor is to be configured and the UserDescription field shall contain the ASCII character string that is to be configured in the user descriptor. IN: The buffer where the request data will be filled in. IN: The package with the request information. IN: The destination address where the message will be send. */ zbSize_t User_Desc_set ( uint8_t *pkgPayload, /* IN: The buffer where the request data will be filled in. */ zbUserDescriptorSet_t *pMessageComingIn, /* IN: The package with the request information. */ zbNwkAddr_t aDestAddr /* IN: The destination address where the message will be send. */ ) { zbSize_t payloadLength; FLib_MemSet(pkgPayload, 0x20, sizeof(zbUserDescriptorSet_t)); payloadLength = (MbrOfs(zbUserDescriptorSet_t, descriptor.aUserDescription[0]) + pMessageComingIn->descriptor.length); FLib_MemCpy(pkgPayload, pMessageComingIn,payloadLength); Zdp_GenerateDataReq( gUser_Desc_set_c, aDestAddr, (afToApsdeMessage_t *)(pkgPayload -SapHandlerDataStructureOffSet), sizeof(zbUserDescriptorSet_t) ); return gZdpAlreadyHanlded_c; }
/*-------------------- Mgmt_NWK_Update_req -------------------- 2.4.3.3.9 Mgmt_NWK_Update_req. (ClusterID=0x0038) This command is provided to allow updating of network configuration parameters or to request information from devices on network conditions in the local operating environment. The destination addressing on this primitive shall be unicast or broadcast to all devices for which macRxOnWhenIdle = TRUE. */ zbSize_t Mgmt_NWK_Update_req ( zbMgmtNwkUpdateRequest_t *pRequest, zbNwkAddr_t aDestAddr ) { zbSize_t size = MbrOfs(zbMgmtNwkUpdateRequest_t, ExtraData); if (!ZdoGetNwkManagerBitMask(gaServerMask)) { (void) pRequest; (void) aDestAddr; (void) size; return gZero_c; } if (!IsValidNwkUnicastAddr(aDestAddr) && !IsEqual2Bytes(aDestAddr,gaBroadcastRxOnIdle)) { /* Consider it as an invalid request. */ return gZero_c; } /* The values 0x00 and 0x05 are acording to the Table 2.87 Fields of the Mgmt_NWK_Update_req Command , since is a the ScanDuration is a uint8 then it is not necesary to make the verification "pRequest->ScanDuration >= 0x00", that is why is commented. */ /* Do a scan. */ if ( pRequest->ScanDuration <= 0x05) { return (size + MbrSizeof(zbudata_t, ScanCount)); } /* Channel channel. */ else if (pRequest->ScanDuration == 0xfe) { #if gFrequencyAgilityCapability_d /* This is a special case, is when the application commands the channge with out using the state machine. */ if (ZdoGetNwkManagerBitMask(gaServerMask)&&(FA_GetNwkManagerState() == gInitState_c)) { /* Place holder to the state machine of the Nwk Manager, to avoid hiting the same state many times. */ FA_SetNwkManagerState(gSelfChannelChange_c); /* Send the same command to our selfs, in order to use the mechanism. */ ASL_Mgmt_NWK_Update_req(NlmeGetRequest(gNwkShortAddress_c), /* To Us. */ pRequest->aScanChannels, /* Same Channel list ot be use. */ 0xfe, /* Do a channel change. */ pRequest->ExtraData.NwkManagerData.nwkUpdateId); /* No scan duration, is a channel change. */ } /* This will make ZDP send the request to other devices. */ return (size + MbrSizeof(zbNwkManagerData_t, nwkUpdateId)); #endif } /* Update NwkUpdateId and channel list. */ else if(pRequest->ScanDuration == 0xff) { return (size + MbrSizeof(zbNwkManagerData_t, nwkUpdateId) + MbrSizeof(zbNwkManagerData_t, aNwkManagerAddr)); } /* For any other value of Scanduration then it only needs the Scan Count. */ return (size + MbrSizeof(zbudata_t, ScanCount)); }
/****************************** Illuminance Measurement Cluster See ZCL Specification Section 4.2 *******************************/ /****************************** Illuminance Level Sensing Cluster See ZCL Specification Section 4.3 *******************************/ /****************************** Temperature Measurement Cluster See ZCL Specification Section 4.4 *******************************/ const zclAttrDef_t gaZclTemperatureMeasurementClusterAttrDef[] = { {gZclAttrTemperatureMeasurement_MeasuredValueId_c, gZclDataTypeInt16_c,gZclAttrFlagsInRAM_c | gZclAttrFlagsReportable_c,sizeof(int16_t), (void *)MbrOfs(zclTemperatureMeasurementAttrs_t,MeasuredValue)}, {gZclAttrTemperatureMeasurement_MinMeasuredValuedId_c, gZclDataTypeInt16_c,gZclAttrFlagsInRAM_c | gZclAttrFlagsRdOnly_c,sizeof(int16_t), (void *)MbrOfs(zclTemperatureMeasurementAttrs_t,MinMeasuredValue)}, {gZclAttrTemperatureMeasurement_MaxMeasuredValuedId_c, gZclDataTypeInt16_c,gZclAttrFlagsInRAM_c | gZclAttrFlagsRdOnly_c,sizeof(int16_t), (void *)MbrOfs(zclTemperatureMeasurementAttrs_t,MaxMeasuredValue)} #if gZclClusterOptionals_d , {gZclAttrTemperatureMeasurement_ToleranceId_c, gZclDataTypeUint16_c,gZclAttrFlagsInRAM_c | gZclAttrFlagsReportable_c,sizeof(uint16_t), (void *)MbrOfs(zclTemperatureMeasurementAttrs_t,Tolerance)} #endif }; const zclAttrDefList_t gZclTemperatureMeasurementClusterAttrDefList = { NumberOfElements(gaZclTemperatureMeasurementClusterAttrDef), gaZclTemperatureMeasurementClusterAttrDef }; /****************************** Pressure Measurement Cluster See ZCL Specification Section 4.5
void HcOutgoingZtcTaskEventMonitor(OepOutgoingMessage_t *message) { hcZtcMessage_t* pMsgFromSAPHandler; /* cleaner access to the 11073 apdu */ oepGenericApdu_t *pApdu = (oepGenericApdu_t *)message->pApdu; uint8_t* pSrcDataPtr; uint8_t* pDstDataPtr; /* first fragment flag is initially set to True */ uint8_t firstFragment = TRUE; uint16_t apduLen = message->length - MbrSizeof(oepGenericApdu_t, apduLen); uint8_t dataCopyLen; /* iterate the fragments */ do { /* allocate a new buffer as the ZTC frames are quite different from the actual 11073 frames */ pMsgFromSAPHandler = (hcZtcMessage_t *) MSG_Alloc(mSapHandlerMsgTotalLen_c); if (firstFragment) { oepMsgType_t oepMsgType; firstFragment = FALSE; /* is it a cfg, prst, other kind of frame? */ oepMsgType = GetOepMsgType(pApdu); /* get ZTC opcode id for the frame */ pMsgFromSAPHandler->msgType = GetMsgZtcOpCode(pApdu); /* frame is an object configuration frame */ if (oepMsgType == msgType_ObjCfgMsg) { hcZtcObjCfgFrame_t* pHcZtcObjCfgFrame = (hcZtcObjCfgFrame_t *)pMsgFromSAPHandler->data; apduLen -= MbrSizeof(oepGenericApdu_t, choice); if (apduLen > mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame)) { dataCopyLen = mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame); apduLen -= dataCopyLen; pHcZtcObjCfgFrame->nextFragmentPresent = TRUE; } else { dataCopyLen = (uint8_t)apduLen; apduLen = 0; pHcZtcObjCfgFrame->nextFragmentPresent = FALSE; } pMsgFromSAPHandler->msgLen = dataCopyLen + MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame); pSrcDataPtr = (uint8_t *)pApdu->payload; pDstDataPtr = (uint8_t *)pHcZtcObjCfgFrame->objCfgFrame; pHcZtcObjCfgFrame->endPoint = message->srcEndPoint; } else { /* Aarq, Aars, Prst, etc type of frame */ hcZtcFrame_t* pZtcFrameGeneric = (hcZtcFrame_t *)pMsgFromSAPHandler->data; if (apduLen > mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcFrame_t, apdu)) { dataCopyLen = mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcFrame_t, apdu); apduLen -= dataCopyLen; pZtcFrameGeneric->nextFragmentPresent = TRUE; } else { dataCopyLen = (uint8_t)apduLen; apduLen = 0; pZtcFrameGeneric->nextFragmentPresent = FALSE; } pMsgFromSAPHandler->msgLen = dataCopyLen + MbrOfs(hcZtcFrame_t, apdu); pSrcDataPtr = (uint8_t *)&pApdu->choice; pDstDataPtr = (uint8_t *)pZtcFrameGeneric->apdu; Copy2Bytes(pZtcFrameGeneric->aSrcDstAddr, message->aDstAddr); pZtcFrameGeneric->dstEndPoint = message->dstEndPoint; pZtcFrameGeneric->srcEndPoint = message->srcEndPoint; } } else { /* this is not the first fragment; */ hcZtcFragmentContinuationFrame_t* pZtcFragmentCont = (hcZtcFragmentContinuationFrame_t *)pMsgFromSAPHandler->data; /* set fragment continuation opcode */ pMsgFromSAPHandler->msgType = gHcZtcOpcode_FragmentContinuation_d; if (apduLen > mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcFragmentContinuationFrame_t, fragmentData)) { dataCopyLen = mSapHandlerMsgTotalLen_c - MbrOfs(hcZtcFragmentContinuationFrame_t, fragmentData); apduLen -= dataCopyLen; pZtcFragmentCont->nextFragmentPresent = TRUE; } else { dataCopyLen = (uint8_t)apduLen; apduLen = 0; pZtcFragmentCont->nextFragmentPresent = FALSE; } pMsgFromSAPHandler->msgLen = dataCopyLen + MbrSizeof(hcZtcFragmentContinuationFrame_t, fragmentData); pDstDataPtr = (uint8_t *)pZtcFragmentCont->fragmentData; } FLib_MemCpy(pDstDataPtr, pSrcDataPtr, dataCopyLen); pSrcDataPtr += dataCopyLen; /* send message to ZTC */ #ifndef gHostApp_d ZTC_TaskEventMonitor(gHcApp_SAPHandlerId_c, (uint8_t *)pMsgFromSAPHandler, gZbSuccess_c); #else ZTC_TaskEventMonitor(gpHostAppUart, gHcApp_SAPHandlerId_c, (uint8_t *)pMsgFromSAPHandler, gZbSuccess_c); #endif /* free the message if ZTC hasn't already done that */ if (pMsgFromSAPHandler) MSG_Free(pMsgFromSAPHandler); } while (apduLen > 0); }
void HcIncomingZtcTaskEventMonitor(OepFragmentedApdu_t *message) { hcZtcMessage_t* pMsgFromSAPHandler; /* pCurrentFragment points initially to the fragment in OepFragmentedApdu_t */ OepApduFragment_t* pCurrentFragment = &message->fragment; /* cleaner access to the 11073 apdu */ oepGenericApdu_t *pApdu = (oepGenericApdu_t *)pCurrentFragment->data; /* first fragment flag is initially set to True */ uint8_t firstFragment = TRUE; /* iterate the fragments */ do { uint8_t srcOffset, dstOffset, dataCopyLen; /* allocate a new buffer as the ZTC frames are quite different from the actual 11073 frames */ pMsgFromSAPHandler = (hcZtcMessage_t *) MSG_Alloc(mSapHandlerMsgTotalLen_c); /* set default values for mem copy offsets and length */ /* by default copy data beginning with the choice member in the apdu */ srcOffset = MbrOfs(oepGenericApdu_t, choice); /* by default copy data to the apdu member in the ztc frame*/ dstOffset = MbrOfs(hcZtcFrame_t, apdu); /* data copy length adjusted to omit apduLen field */ dataCopyLen = pCurrentFragment->len - MbrOfs(oepGenericApdu_t, choice); if (firstFragment) { oepMsgType_t oepMsgType; firstFragment = FALSE; /* is it a cfg, prst, other kind of frame? */ oepMsgType = GetOepMsgType(pApdu); /* get ZTC opcode id for the frame */ pMsgFromSAPHandler->msgType = GetMsgZtcOpCode(pApdu); /* frame is an object configuration frame */ if (oepMsgType == msgType_ObjCfgMsg) { /* msgLen is the length of the ZTC payload; this includes the actual apdu payload, without the choice and apduLen as well as the src/dstEndPoint and nextFragmentPresent bytes */ pMsgFromSAPHandler->msgLen = (uint8_t)(pCurrentFragment->len - MbrOfs(oepGenericApdu_t, payload) + MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame)); /* adjust source offset for data copy to not include choice */ srcOffset = MbrOfs(oepGenericApdu_t, payload); /* adjust dst offset for data copy as srcAddress and an endpoint are no longer included */ dstOffset = MbrOfs(hcZtcObjCfgFrame_t, objCfgFrame); /* adjust data length for data copy as choice is no longer included */ dataCopyLen -= MbrSizeof(oepGenericApdu_t, choice); /* set destination endpoint as second byte in the ZTC packet based on frame direction */ pMsgFromSAPHandler->data[1] = message->dstEndPoint; } else { /* Aarq, Aars, Prst, etc type of frame */ hcZtcFrame_t* pZtcFrameGeneric = (hcZtcFrame_t *)pMsgFromSAPHandler->data; /* msgLen is the length of the ZTC payload; this includes the actual apdu payload, without the apduLen as well as the addressing information and nextFragmentPresent bytes */ pMsgFromSAPHandler->msgLen = pCurrentFragment->len - MbrOfs(oepGenericApdu_t, choice) + MbrOfs(hcZtcFrame_t, apdu); /* copy addressing info */ Copy2Bytes(pZtcFrameGeneric->aSrcDstAddr, message->aSrcAddr); pZtcFrameGeneric->dstEndPoint = message->dstEndPoint; pZtcFrameGeneric->srcEndPoint = message->srcEndPoint; } } else { /* this is not the first fragment; */ /* set data copy and copy size accordingly */ srcOffset = 0; dstOffset = 1; dataCopyLen = pCurrentFragment->len; pApdu = (oepGenericApdu_t *)pCurrentFragment->data; /* set fragment continuation opcode */ pMsgFromSAPHandler->msgType = gHcZtcOpcode_FragmentContinuation_d; /* msgLen includes the actualapdu payload and the nextFragmentPresent byte */ pMsgFromSAPHandler->msgLen = pCurrentFragment->len + MbrSizeof(hcZtcFrame_t, nextFragmentPresent); } /* nextFragmentPresent */ pMsgFromSAPHandler->data[0] = FALSE; /* set nextFramgentPresent byte in ZTC frame to 1 if there is another fragment to be processed */ if (pCurrentFragment->nextFragment != NULL) pMsgFromSAPHandler->data[0] = TRUE; /* do the fragment iteration */ pCurrentFragment = pCurrentFragment->nextFragment; /* copy payload data */ FLib_MemCpy((uint8_t*)pMsgFromSAPHandler->data + dstOffset, (uint8_t*)pApdu + srcOffset, dataCopyLen); /* send message to ZTC */ #ifndef gHostApp_d ZTC_TaskEventMonitor(gAppHc_SAPHandlerId_c, (uint8_t *)pMsgFromSAPHandler, gZbSuccess_c); #else ZTC_TaskEventMonitor(gpHostAppUart, gAppHc_SAPHandlerId_c, (uint8_t *)pMsgFromSAPHandler, gZbSuccess_c); #endif /* free the message if ZTC hasn't already done that */ if (pMsgFromSAPHandler) MSG_Free(pMsgFromSAPHandler); } while (pCurrentFragment != NULL); }