/* ** SRV_NEventReportResponse ** ** Purpose: ** SRV_NEventReportResponse assists an application that wants to be an SCU ** of a number of SOP classes. When an application receives an ** N-EVENT_REPORT request message, it calls this function with the ** N-EVENT_REPORT request and other parameters. SRV_NEventReportResponse ** checks the caller's parameters and calls the user's callback function. ** In the callback function, the caller fills in the parameters of the ** N-EVENT_REPORT response message and then returns to the SRV function. ** ** After the callback function returns, SRV_NEventReportResponse ** constructs a N-EVENT_REPORT Response message and sends it to the peer ** application which sent the request message. ** ** The arguments to the callback function are: ** MSG_N_EVENT_REPORT_REQ *eventRequest ** MSG_N_EVENT_REPORT_RESP *eventResponse ** void *eventCtx ** DUL_PRESENTATIONCONTEXT *pc ** ** The first two arguments are MSG structures that contain the ** N-EVENT_REPORT Request and N-EVENT_REPORT Response messages ** respectively. The third argument is the caller's context variable that ** is passed to SRV_NEventReportResponse. The presentation context is ** the one negotiated for this SOP class. ** ** The callback function should return SRV_NORMAL. Any other return ** value will cause the SRV facility to abort the Association. ** ** Parameter Dictionary: ** association The key which is used for transmitting the ** N-EVENT_REPORT response. ** presentationCtx Pointer to presentation context to be used when sending ** the N-EVENT_REPORT response. ** eventRequest Pointer to the structure with the N-EVENT_REPORT request ** parameters which was received by the application. ** eventResponse Pointer to structure in the caller's area which will be ** filled with the parameters of the N-EVENT_REPORT ** response command. After the parameters are filled in, ** the N-EVENT_REPORT response is sent to the peer ** application which sent the request. ** eventCallback Address of user callback function to be called ** with the N-EVENT_REPORT response from SCU. ** eventCtx Pointer to user context information which will be ** passed to the callback function. Caller uses this ** variable to contain any context required for the ** callback function. ** dirName Name of directory where files may be created. ** ** ** Return Values: ** ** SRV_CALLBACKABORTEDSERVICE ** SRV_ILLEGALPARAMETER ** SRV_NOCALLBACK ** SRV_NORMAL ** SRV_OBJECTBUILDFAILED ** SRV_RESPONSEFAILED ** ** Algorithm: ** Receive a data set, if any, from the peer application ** Invoke the callback function, if it exists. ** Build a command and send it to the requesting peer application. ** Send a data set, if any, to the peer application. ** ** Notes: ** The callback function is responsible for explicitly setting the ** following fields in the N-EVENT_REPORT request message: ** ** type ** messageIDRespondedTo ** classUID ** dataSetType ** instanceUID ** status ** */ CONDITION SRV_NEventReportResponse(DUL_ASSOCIATIONKEY ** association, DUL_PRESENTATIONCONTEXT * presentationCtx, MSG_N_EVENT_REPORT_REQ ** eventRequest, MSG_N_EVENT_REPORT_RESP * eventResponse, SRV_N_EVENTREPORT_RESP_CALLBACK * eventCallback, void *eventCtx, char *dirName) { CONDITION cond; DCM_OBJECT * responseObject; eventResponse->status = MSG_K_SUCCESS; if (eventCallback == NULL) { (void) MSG_Free((void **) eventRequest); return COND_PushCondition(SRV_NOCALLBACK, SRV_Message(SRV_NOCALLBACK), "SRV_NEventReportResponse"); } if ((*eventRequest)->dataSetType != DCM_CMDDATANULL){ cond = SRV_ReceiveDataSet(association, presentationCtx, DUL_BLOCK, 0, dirName, &(*eventRequest)->dataSet); if (cond != SRV_NORMAL){ (void) MSG_Free((void **) eventRequest); return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_NEventReportResponse"); } } eventResponse->dataSetType = DCM_CMDDATANULL; cond = DCM_CreateObject(&eventResponse->dataSet, 0); if (cond != DCM_NORMAL) { (void) MSG_Free((void **) eventRequest); return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_NEventReportResponse"); } cond = eventCallback(*eventRequest, eventResponse, eventCtx, presentationCtx); (void) MSG_Free((void **) eventRequest); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_NEventReportRequest"); if (eventResponse->type != MSG_K_N_EVENT_REPORT_RESP) return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "type", "N-EVENT_REPORT Response", "SRV_NEventReportResponse"); cond = MSG_BuildCommand(eventResponse, &responseObject); if (cond != MSG_NORMAL) { (void) DCM_CloseObject(&eventResponse->dataSet); return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "N-EVENT_REPORT Response", "SRV_NEventReportResponse"); } cond = SRV_SendCommand(association, presentationCtx, &responseObject); (void) DCM_CloseObject(&responseObject); if (cond != SRV_NORMAL) { (void) DCM_CloseObject(&eventResponse->dataSet); return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_NEventReportResponse"); } if (eventResponse->dataSetType != DCM_CMDDATANULL){ /* application specific event reply exists */ cond = SRV_SendDataSet(association, presentationCtx, &eventResponse->dataSet, NULL, NULL, 0); if (cond != SRV_NORMAL){ (void) DCM_CloseObject(&eventResponse->dataSet); return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_NEventReportResponse"); } } (void) DCM_CloseObject(&eventResponse->dataSet); return SRV_NORMAL; }
/***************************************************************************** BeeAppInterPanDataIndication Process InterPan incoming ZigBee over-the-air messages. *****************************************************************************/ void BeeAppInterPanDataIndication(void) { InterPanMessage_t *pMsg; zbInterPanDataIndication_t *pIndication; zbStatus_t status = gZclMfgSpecific_c; while(MSG_Pending(&gInterPanAppDataIndicationQueue)) { /* Get a message from a queue */ pMsg = MSG_DeQueue( &gInterPanAppDataIndicationQueue ); /* ask ZCL to handle the frame */ pIndication = &(pMsg->msgData.InterPandataIndication ); status = ZCL_InterpretInterPanFrame(pIndication); /* not handled by ZCL interface, handle cluster here... */ if(status == gZclMfgSpecific_c) { /* insert manufacturer specific code here... */ } /* Free memory allocated by data indication */ MSG_Free(pMsg); } }
/***************************************************************************** BeeAppDataConfirm Process incoming ZigBee over-the-air data confirms. *****************************************************************************/ void BeeAppDataConfirm(void) { apsdeToAfMessage_t *pMsg; zbApsdeDataConfirm_t *pConfirm; while(MSG_Pending(&gAppDataConfirmQueue)) { /* Get a message from a queue */ pMsg = MSG_DeQueue( &gAppDataConfirmQueue ); pConfirm = &(pMsg->msgData.dataConfirm); /* Action taken when confirmation is received. */ if( pConfirm->status != gZbSuccess_c ) { /* The data wasn't delivered -- Handle error code here */ } /* Free memory allocated in Call Back function */ MSG_Free(pMsg); } }
CONDITION SRV_CGetResponse(DUL_ASSOCIATIONKEY ** association, DUL_ASSOCIATESERVICEPARAMETERS * params, DUL_PRESENTATIONCONTEXT * getPresentationCtx, MSG_C_GET_REQ ** getRequest, MSG_C_GET_RESP * getResponse, SRV_C_GET_RESP_CALLBACK * getCallback, void *getCtx, char *dirName) { int flag, responseCount = 0; U32 l; char queryLevelString[48] = ""; /* Initialization for AIX compiler */ CONDITION cond, rtnCond = SRV_NORMAL; DCM_OBJECT * responseObject; /* get response object */ void *ctx; DCM_ELEMENT queryLevelElement = {DCM_IDQUERYLEVEL, DCM_CS, "", 1, sizeof(queryLevelString), NULL}; static char *allowedQueryLevels[] = { DCM_QUERYLEVELPATIENT, DCM_QUERYLEVELSTUDY, DCM_QUERYLEVELSERIES, DCM_QUERYLEVELIMAGE}; MSG_STATUS_DESCRIPTION statusDescription; char pendingMsg[] = "\ In SRV_CGetResponse, the response message returned by your callback has \n\ a status of pending and data set that is not null.\n"; MSG_TYPE messageType; void *message; DUL_PRESENTATIONCONTEXTID ctxID; MSG_C_STORE_REQ storeRequest; char classUID[DICOM_UI_LENGTH + 1]; queryLevelElement.d.string = queryLevelString; if (getCallback == NULL) { (void) MSG_Free((void **) getRequest); return COND_PushCondition(SRV_NOCALLBACK, SRV_Message(SRV_NOCALLBACK), "SRV_CGetResponse"); } if (getResponse->type != MSG_K_C_GET_RESP) { (void) MSG_Free((void **) getRequest); return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "type", "GET Request", "SRV_CGetResponse"); } (void) strcpy(classUID, (*getRequest)->classUID); cond = DCM_CreateObject(&getResponse->identifier, 0); if (cond != DCM_NORMAL) return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse"); cond = SRV_ReceiveDataSet(association, getPresentationCtx, DUL_BLOCK, 0, dirName, &(*getRequest)->identifier); if (PRVSRV_debug && (cond == SRV_NORMAL)) (void) DCM_DumpElements(&(*getRequest)->identifier, 0); if (cond != SRV_NORMAL) { (void) MSG_Free((void **) getRequest); return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse"); } ctx = NULL; cond = DCM_GetElementValue(&(*getRequest)->identifier, &queryLevelElement, &l, &ctx); if (cond != DCM_NORMAL) { (void) MSG_Free((void **) getRequest); (void) COND_PushCondition(SRV_QUERYLEVELATTRIBUTEMISSING, SRV_Message(SRV_QUERYLEVELATTRIBUTEMISSING), "SRV_CGetResponse"); return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse"); } queryLevelString[l] = '\0'; if (queryLevelString[l - 1] == ' ') queryLevelString[l - 1] = '\0'; for (flag = 0, l = 0; l < DIM_OF(allowedQueryLevels) && !flag; l++){ if (strcmp(queryLevelString, allowedQueryLevels[l]) == 0) flag = 1; } if (!flag) { (void) MSG_Free((void **) getRequest); (void) COND_PushCondition(SRV_ILLEGALQUERYLEVELATTRIBUTE, SRV_Message(SRV_ILLEGALQUERYLEVELATTRIBUTE), queryLevelString, "SRV_CGetResponse"); return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse"); } getResponse->messageIDRespondedTo = (*getRequest)->messageID; getResponse->conditionalFields = 0; getResponse->remainingSubOperations = 0; getResponse->completedSubOperations = 0; getResponse->failedSubOperations = 0; getResponse->warningSubOperations = 0; /* * Fill up the Store request and let the callback routine do the matching * and fill the rest of the fields */ storeRequest.type = MSG_K_C_STORE_REQ; storeRequest.conditionalFields = 0; storeRequest.messageID = SRV_MessageIDOut(); storeRequest.priority = 0; storeRequest.moveMessageID = (*getRequest)->messageID; /* * We invoke the callback for the first time without any StoreResponse so * that the callback can deal with the query and fill the Store Request * message and the GET response message. We also pass responseCount as 0 * when we invoke the callback for the first time */ cond = getCallback(*getRequest, getResponse, &storeRequest, NULL, 0, getPresentationCtx->abstractSyntax, queryLevelString, getCtx); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_CGetRespose"); if (storeRequest.dataSetType != DCM_CMDDATANULL) { /* Send a Store Request */ cond = sendStoreRequest(association, params, &storeRequest); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_SENDFAILED, SRV_Message(SRV_SENDFAILED),"sendStoreRequest", "SRV_CGetResponse"); }else{ /* * No images are to be transferred as the query may have been * unsuccessful in the call back routine. We expect the callback * routine to have supplied the appropriate values for the various * fields of the getResponse message. * * Send the CGetResponse Message and return from the routine */ cond = MSG_BuildCommand(getResponse, &responseObject); if (cond != MSG_NORMAL) return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "getResponse", "SRV_CGetResponse"); cond = SRV_SendCommand(association, getPresentationCtx, &responseObject); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_SENDFAILED, SRV_Message(SRV_SENDFAILED),"SRV_SendCommand", "SRV_CGetResponse"); if (getResponse->dataSetType != DCM_CMDDATANULL) { cond = SRV_SendDataSet(association, getPresentationCtx, &getResponse->identifier, NULL, NULL, 0); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_SENDFAILED, SRV_Message(SRV_SENDFAILED), "SRV_SendDataSet", "SRV_CGetResponse"); } return SRV_NORMAL; } flag = 0; while (!flag) { /* * Now wait for incoming Store Responses or a Cancel Request. If it * is a Store Response, invoke the callback routine, with the Store * Response. The callback will update the Get Response message * accordingly and also fill the Store Request message if any more * requests are to be made */ cond = SRV_ReceiveCommand(association, params, DUL_BLOCK, 0, &ctxID, NULL, &messageType, (void **) &message); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_RECEIVEFAILED, SRV_Message(SRV_RECEIVEFAILED), "SRV_CGetResponse"); switch (messageType) { case MSG_K_C_CANCEL_REQ: rtnCond = SRV_OPERATIONCANCELLED; getResponse->status = MSG_K_CANCEL; (void) MSG_Free(&message); cond = getCallback(*getRequest, getResponse, NULL, NULL, responseCount, getPresentationCtx->abstractSyntax, queryLevelString, getCtx); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_CGetRespose"); getResponse->messageIDRespondedTo = (*getRequest)->messageID; break; case MSG_K_C_STORE_RESP: responseCount++; getResponse->dataSetType = DCM_CMDDATANULL; getResponse->status = 0xffff; /* * Fill up the Store request and let the callback routine do the * matching and fill the rest of the fields */ storeRequest.type = MSG_K_C_STORE_REQ; storeRequest.conditionalFields = 0; storeRequest.messageID = SRV_MessageIDOut(); storeRequest.priority = 0; storeRequest.moveMessageID = (*getRequest)->messageID; cond = getCallback(*getRequest, getResponse, &storeRequest, (MSG_C_STORE_RESP *) message, responseCount, getPresentationCtx->abstractSyntax, queryLevelString, getCtx); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_CGetRespose"); if (storeRequest.dataSetType != DCM_CMDDATANULL) { /* make the next store request */ cond = sendStoreRequest(association, params, &storeRequest); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_SENDFAILED, SRV_Message(SRV_SENDFAILED), "sendStoreRequest", "SRV_CGetResponse"); } break; default: break; } if (cond == SRV_NORMAL) { cond = MSG_StatusLookup(getResponse->status, MSG_K_C_GET_RESP, &statusDescription); if (cond != MSG_NORMAL) return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse"); if (statusDescription.statusClass != MSG_K_CLASS_PENDING) flag = 1; /* Consistency check */ if ((statusDescription.statusClass == MSG_K_CLASS_PENDING) && (getResponse->dataSetType != DCM_CMDDATANULL)) { if (PRVSRV_debug) fprintf(DEBUG_DEVICE, pendingMsg); rtnCond = COND_PushCondition(SRV_SUSPICIOUSRESPONSE, SRV_Message(SRV_SUSPICIOUSRESPONSE), "C-GET", "pending", "not null", "SRV_CGetResponse"); } }else{ flag = 1; } strcpy(getResponse->classUID, classUID); getResponse->conditionalFields |= MSG_K_C_GETRESP_CLASSUID; cond = MSG_BuildCommand(getResponse, &responseObject); if (cond != MSG_NORMAL) { (void) MSG_Free((void **) getRequest); return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse"); } cond = SRV_SendCommand(association, getPresentationCtx, &responseObject); if (cond != SRV_NORMAL) { (void) MSG_Free((void **) getRequest); return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse"); } if (getResponse->dataSetType != DCM_CMDDATANULL) { cond = SRV_SendDataSet(association, getPresentationCtx, &getResponse->identifier, NULL, NULL, 0); if (cond != SRV_NORMAL) { (void) MSG_Free((void **) getRequest); return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CGetResponse"); } } } (void) MSG_Free((void **) getRequest); return rtnCond; }
CONDITION SRV_CGetRequest(DUL_ASSOCIATIONKEY ** association, DUL_ASSOCIATESERVICEPARAMETERS * params, MSG_C_GET_REQ * getRequest, MSG_C_GET_RESP * getResponse, SRV_C_GET_REQ_CALLBACK * getCallback, void *getCallbackCtx, CONDITION(*storageCallback) (), void *storageCallbackCtx, char *dirName) { DCM_OBJECT * commandObject; /* Handle for a command object */ CONDITION cond; /* Return value from function calls */ DUL_PRESENTATIONCONTEXT * presentationCtx, /* Presentation context for GET service */ *storePresentationCtx; /* for the arriving store request */ DUL_PRESENTATIONCONTEXTID ctxID; void *message; MSG_TYPE messageType; CTNBOOLEAN done = FALSE; U32 l; unsigned long responseCount = 0; MSG_C_STORE_REQ * storeRequest; void *ctx; char queryLevelString[48] = ""; /* Initialization for AIX compiler */ DCM_ELEMENT queryLevelElement = {DCM_IDQUERYLEVEL, DCM_CS, "", 1, sizeof(queryLevelString), NULL}; unsigned short command; CTNBOOLEAN cancelled = FALSE; MSG_C_CANCEL_REQ cancelRequest = {MSG_K_C_CANCEL_REQ, 0, 0, DCM_CMDDATANULL}; queryLevelElement.d.string = queryLevelString; if ((getCallback == NULL) || (storageCallback == NULL)) return COND_PushCondition(SRV_NOCALLBACK, SRV_Message(SRV_NOCALLBACK), "SRV_CGetRequest"); if (getRequest->type != MSG_K_C_GET_REQ) return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "type", "GET Request", "SRV_CGetRequest"); if (getRequest->dataSetType == DCM_CMDDATANULL) return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "dataSetType", "GET Request", "SRV_CGetRequest"); ctx = NULL; cond = DCM_GetElementValue(&getRequest->identifier, &queryLevelElement, &l, &ctx); if (cond != DCM_NORMAL) return COND_PushCondition(SRV_OBJECTACCESSFAILED, SRV_Message(SRV_OBJECTACCESSFAILED), "Query Identifier", "SRV_CGetRequest"); queryLevelString[l] = '\0'; if (queryLevelString[l - 1] == ' ') queryLevelString[l - 1] = '\0'; presentationCtx = SRVPRV_PresentationContext(params, getRequest->classUID); if (presentationCtx == NULL) return COND_PushCondition(SRV_NOSERVICEINASSOCIATION, SRV_Message(SRV_NOSERVICEINASSOCIATION), getRequest->classUID, "SRV_CGetRequest"); cond = MSG_BuildCommand(getRequest, &commandObject); if (cond != MSG_NORMAL) return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "GET Request", "SRV_CGetRequest"); cond = SRV_SendCommand(association, presentationCtx, &commandObject); (void) DCM_CloseObject(&commandObject); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CGetRequest"); cond = SRV_SendDataSet(association, presentationCtx, &getRequest->identifier, NULL, NULL, 0); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CGetRequest"); while (!done) { /* do until there are no more pending requests */ cond = SRV_ReceiveCommand(association, params, DUL_BLOCK, 0, &ctxID, &command, &messageType, &message); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CGetRequest"); switch (messageType) { case MSG_K_C_GET_RESP: cond = processGetResponse(association, presentationCtx, dirName, getRequest, (MSG_C_GET_RESP *) message, queryLevelString, getCallback, getCallbackCtx, &done, &cancelled, getResponse, &responseCount); (void) MSG_Free(&message); if ((CTN_FATAL(cond)) || (CTN_ERROR(cond))) return cond; break; case MSG_K_C_STORE_REQ: storeRequest = (MSG_C_STORE_REQ *) message; storePresentationCtx = SRVPRV_PresentationContext(params, storeRequest->classUID); if (storePresentationCtx == NULL) return COND_PushCondition(SRV_PRESENTATIONCONTEXTERROR, SRV_Message(SRV_PRESENTATIONCONTEXTERROR), "SRV_CGetRequest"); cond = processStoreRequest(association, storePresentationCtx, storeRequest, storageCallback, storageCallbackCtx); if ((CTN_FATAL(cond)) || (CTN_ERROR(cond))) return cond; break; default: (void) MSG_Free(&message); return COND_PushCondition(SRV_UNEXPECTEDCOMMAND, SRV_Message(SRV_UNEXPECTEDCOMMAND), (int) command, "SRV_CGetRequest"); } } if (cancelled){ return SRV_OPERATIONCANCELLED; }else{ return SRV_NORMAL; } }
/* SRV_NActionResponse ** ** Purpose: ** SRV_NActionResponse assists an application that wants to be an SCP ** of a number of SOP classes. When an application receives an N-ACTION ** request message, it calls this function with the N-ACTION request ** and other parameters. SRV_NActionResponse checks the caller's ** parameters and calls the user's callback function. In the callback ** function, the caller fills in the parameters of the N-ACTION response ** message and then returns to the SRV function. ** ** After the callback function returns, SRV_NActionResponse constructs a ** N-ACTION Response message and sends it to the peer application which ** sent the request message. ** ** The arguments to the callback function are: ** MSG_N_ACTION_REQ *actionRequest ** MSG_N_ACTION_RESP *actionResponse ** void *actionCtx ** DUL_PRESENTATIONCONTEXT *pc ** ** The first two arguments are MSG structures that contain the N-ACTION ** Request and N-ACTION Response messages respectively. The third ** argument is the caller's context variable that is passed to ** SRV_NActionResponse. The presentation context describes the SOP ** class that was negotiated for this message. ** ** The callback function should return SRV_NORMAL. Any other return ** value will cause the SRV facility to abort the Association. ** ** Parameter Dictionary: ** association The key which is used for transmitting the N-ACTION ** response. ** presentationCtx Pointer to presentation context to be used when sending ** the N-ACTION response. ** actionRequest Pointer to the structure with the N-ACTION request ** parameters which was received by the application. ** actionResponse Pointer to structure in the caller's area which will be ** filled with the parameters of the N-ACTION response ** command. After the parameters are filled in, the ** N-ACTION response is sent to the peer application ** which sent the request. ** actionCallback Address of user callback function to be called ** with the N-ACTION response from SCP. ** actionCtx Pointer to user context information which will be ** passed to the callback function. Caller uses this ** variable to contain any context required for the ** callback function. ** dirName Name of directory where files may be created. ** ** ** Return Values: ** ** SRV_CALLBACKABORTEDSERVICE ** SRV_ILLEGALPARAMETER ** SRV_NOCALLBACK ** SRV_NORMAL ** SRV_OBJECTBUILDFAILED ** SRV_RESPONSEFAILED ** ** Algorithm: ** Receive a data set, if any, from the peer application ** Invoke the callback function, if it exists. ** Build a command and send it to the requesting peer application. ** Send a data set, if any, to the peer application. ** ** Notes: ** The callback function is responsible for explicitly setting the ** following fields in the N-ACTION response message: ** ** type ** messageIDRespondedTo ** classUID ** dataSetType ** instanceUID ** status ** actionReply (if any) ** */ CONDITION SRV_NActionResponse(DUL_ASSOCIATIONKEY ** association, DUL_PRESENTATIONCONTEXT * presentationCtx, MSG_N_ACTION_REQ ** actionRequest, MSG_N_ACTION_RESP * actionResponse, SRV_N_ACTION_RESP_CALLBACK * actionCallback, void *actionCtx, char *dirName) { CONDITION rtnCond = SRV_NORMAL, cond; DCM_OBJECT * responseObject = NULL; actionResponse->status = MSG_K_SUCCESS; /* initialize */ actionResponse->dataSetType = DCM_CMDDATANULL; actionResponse->actionReply = NULL; if (actionCallback == NULL) { rtnCond = COND_PushCondition(SRV_NOCALLBACK, SRV_Message(SRV_NOCALLBACK), "SRV_NActionResponse"); actionResponse->status = MSG_K_RESOURCELIMITATION; goto SEND_RESPONSE; } /* check if there is any data coming over the network */ if ((*actionRequest)->dataSetType != DCM_CMDDATANULL) { cond = SRV_ReceiveDataSet(association, presentationCtx, DUL_BLOCK, 0, dirName, &(*actionRequest)->actionInformation); if (cond != SRV_NORMAL) { rtnCond = COND_PushCondition(SRV_RECEIVEDATASETFAILED, SRV_Message(SRV_RECEIVEDATASETFAILED), "SRV_NActionResponse"); actionResponse->status = MSG_K_PROCESSINGFAILURE; goto SEND_RESPONSE; } } /* SRV routine allocates space for the action reply */ cond = DCM_CreateObject(&actionResponse->actionReply, 0); if (cond != DCM_NORMAL) { rtnCond = COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "SRV_NActionResponse"); actionResponse->status = MSG_K_PROCESSINGFAILURE; goto SEND_RESPONSE; } cond = actionCallback(*actionRequest, actionResponse, actionCtx, presentationCtx); if (cond != SRV_NORMAL) { rtnCond = COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_NActionRequest"); goto SEND_RESPONSE; } if (actionResponse->type != MSG_K_N_ACTION_RESP) { rtnCond = COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "type", "N-ACTION Response", "SRV_NActionResponse"); goto SEND_RESPONSE; } SEND_RESPONSE: /* At this point we free the request pointer */ (void) MSG_Free((void **) actionRequest); /* * If there are any errors in the following steps, it is necessary for * the SRV routine to free the data set object it had created earlier. * But we must verify that such a data set creation operation itself was * successful before we try to free the data set */ /* send the action reply (if any) only on success status */ if (actionResponse->status != MSG_K_SUCCESS) { actionResponse->dataSetType = DCM_CMDDATANULL; if (actionResponse->actionReply) (void) DCM_CloseObject(&actionResponse->actionReply); return rtnCond; } /* build a command object */ cond = MSG_BuildCommand(actionResponse, &responseObject); if (cond != MSG_NORMAL) { if (actionResponse->actionReply) (void) DCM_CloseObject(&actionResponse->actionReply); return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "N-ACTION Response", "SRV_NActionResponse"); } cond = SRV_SendCommand(association, presentationCtx, &responseObject); (void) DCM_CloseObject(&responseObject); if (cond != SRV_NORMAL) { if (actionResponse->actionReply) (void) DCM_CloseObject(&actionResponse->actionReply); return COND_PushCondition(SRV_SENDFAILED, SRV_Message(SRV_SENDFAILED), "Command", "SRV_NActionResponse"); } /* * At this point, the response message status is "SUCCESS". This also * implies that the "data set" object exists but may be empty (not NULL) * Hence if there is any error, we need to close it first before we * return. */ if (actionResponse->dataSetType != DCM_CMDDATANULL) { cond = SRV_SendDataSet(association, presentationCtx, &actionResponse->actionReply, NULL, NULL, 0); if (cond != SRV_NORMAL) { (void) DCM_CloseObject(&actionResponse->actionReply); return COND_PushCondition(SRV_SENDFAILED, SRV_Message(SRV_SENDFAILED), "Data Set", "SRV_NActionResponse"); } } (void) DCM_CloseObject(&actionResponse->actionReply); /* was allocated memory */ return SRV_NORMAL; /* everything is successful at this point */ }
/* SRV_NActionRequest ** ** Purpose: ** SRV_NActionRequest assists an application that wants to be an SCU of ** a number of SOP classes. This function constructs an N-ACTION-REQ ** message and sends it to the peer application which is acting as the ** SCP for a SOP class. This function waits for the response from the ** peer application and invokes the caller's callback function. ** ** The arguments to the callback function are: ** MSG_N_ACTION_REQ *actionRequest ** MSG_N_ACTION_RESP *actionResponse ** void *actionCtx ** ** The first two arguments are MSG structures that contain the N-ACTION ** Request and N-ACTION Response messages respectively. The final ** argument is the caller's context variable that is passed to ** SRV_NActionRequest. ** ** The callback function should return SRV_NORMAL. Any other return ** value will cause the SRV facility to abort the Association. ** ** Parameter Dictionary: ** association The key which is used to access an existing ** association. ** params The list of parameters for the association. This ** list includes the list of presentation contexts. ** SOPClass UID of the SOP class used when the association was ** negotiated. Since this can be a meta class, it may ** not be the same as the class UID in the N-ACTION ** request message. ** actionRequest Pointer to the structure with the N-ACTION request ** parameters. ** actionResponse Pointer to caller's pointer to an N-ACTION response. ** This function will allocate an MSG_N_ACTION_RESP ** message and return the pointer to the caller. ** actionCallback Address of user callback function to be called ** with the N-ACTION response from SCP. ** actionCtx Pointer to user context information which will be ** passed to the callback function. Caller uses this ** variable to contain any context required for the ** callback function. ** dirName Name of directory where files may be created. ** ** ** Return Values: ** ** SRV_CALLBACKABORTEDSERVICE ** SRV_ILLEGALPARAMETER ** SRV_NOCALLBACK ** SRV_NORMAL ** SRV_OBJECTBUILDFAILED ** SRV_REQUESTFAILED ** SRV_UNEXPECTEDCOMMAND ** SRV_UNSUPPORTEDSERVICE ** ** Algorithm: ** Check if the callback function has been provided. ** Determine the presentation context ** Encode the N-ACTION request message as a command object and ** send it to an SCP ** Send data set, if one exists, to the SCP. ** Wait for a response message to arrive from the SCP ** Receive a data set, if one exists, from the SCP ** Return address of Response message structure to caller. ** ** Notes: ** The caller is responsible for explicitly setting the following ** fields in the N-ACTION request message: ** ** type ** messageID ** classUID ** dataSetType ** instanceUID ** actionTypeID ** ** The caller is also responsible for releasing the Response message ** structure after the SRV_NActionRequest function returns, ** using MSG_Free. */ CONDITION SRV_NActionRequest(DUL_ASSOCIATIONKEY ** association, DUL_ASSOCIATESERVICEPARAMETERS * params, char *SOPClass, MSG_N_ACTION_REQ * actionRequest, MSG_N_ACTION_RESP * actionResponse, SRV_N_ACTION_REQ_CALLBACK * actionCallback, void *actionCtx, char *dirName) { DCM_OBJECT * commandObject; /* Handle for a command object */ CONDITION cond; /* Return value from function calls */ DUL_PRESENTATIONCONTEXT * presentationCtx; /* Presentation context for this service */ DUL_PRESENTATIONCONTEXTID ctxID; void *message; MSG_TYPE messageType; MSG_N_ACTION_RESP * localResponse; unsigned short command; if (actionCallback == NULL) return COND_PushCondition(SRV_NOCALLBACK, SRV_Message(SRV_NOCALLBACK), "SRV_NActionRequest"); presentationCtx = SRVPRV_PresentationContext(params, SOPClass); if (presentationCtx == NULL) return COND_PushCondition(SRV_UNSUPPORTEDSERVICE, SRV_Message(SRV_UNSUPPORTEDSERVICE), actionRequest->classUID, "SRV_NActionRequest"); if (actionRequest->type != MSG_K_N_ACTION_REQ) return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "type", "N-ACTION Request", "SRV_NActionRequest"); cond = MSG_BuildCommand(actionRequest, &commandObject); if (cond != MSG_NORMAL) return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "N-ACTION Request", "SRV_NActionRequest"); cond = SRV_SendCommand(association, presentationCtx, &commandObject); (void) DCM_CloseObject(&commandObject); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_NActionRequest"); if (actionRequest->dataSetType != DCM_CMDDATANULL) { /* application specific action information exists */ cond = SRV_SendDataSet(association, presentationCtx, &actionRequest->actionInformation, NULL, NULL, 0); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_NActionRequest"); } cond = SRV_ReceiveCommand(association, params, DUL_BLOCK, 0, &ctxID, &command, &messageType, &message); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_NActionRequest"); if (messageType != MSG_K_N_ACTION_RESP) { (void) MSG_Free(&message); return COND_PushCondition(SRV_UNEXPECTEDCOMMAND, SRV_Message(SRV_UNEXPECTEDCOMMAND), (int) command, "SRV_NActionRequest"); } localResponse = (MSG_N_ACTION_RESP *) message; if (localResponse->dataSetType == DCM_CMDDATANULL) { localResponse->actionReply = NULL; } else { /* application specific action reply needs to be received */ cond = SRV_ReceiveDataSet(association, presentationCtx, DUL_BLOCK, 0, dirName, &localResponse->actionReply); if (cond != SRV_NORMAL) { (void) MSG_Free(&message); return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_NActionRequest"); } } cond = actionCallback(actionRequest, localResponse, actionCtx); (void) MSG_Free(&message); if (localResponse->actionReply != NULL) { (void) DCM_CloseObject(&localResponse->actionReply); localResponse->actionReply = NULL; } if (actionResponse != NULL) *actionResponse = *localResponse; if (cond != SRV_NORMAL) return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_NActionRequest"); return SRV_NORMAL; }
/******************************************************************************* * State machine to send the next report. If it can't get the memory, tries * again later. * * This will concatinate all of the reportable attributes in a single cluster *******************************************************************************/ void ZCL_SendReport(void) { afDeviceDef_t *pDevice; uint8_t payloadLen; uint8_t reportLen; afToApsdeMessage_t *pMsg; /* a message for sending the report */ afAddrInfo_t addrInfo; afClusterDef_t *pCluster; zclFrame_t *pFrame; uint8_t i; zclReportAttr_t *pReportList; BeeUtilZeroMemory(&addrInfo, sizeof(addrInfo)); /* starting over? reset indexes */ if(gfZclReportRestart) { gZclReportDeviceIndex = gZclReportClusterIndex = gAsynchronousClusterIndex = 0; gfZclReportRestart = FALSE; } /* get a buffer to build the next report */ pMsg = AF_MsgAlloc(); if(!pMsg) { gfZclReportRestart = FALSE; ZLC_StartShortReportingTimer(); return; } /* walk through all devices */ while(gZclReportDeviceIndex < gNum_EndPoints_c) { /* make sure this app endpoint is a ZCL device */ pDevice = (afDeviceDef_t *) endPointList[gZclReportDeviceIndex].pDevice; /* report list */ pReportList = pDevice->pReportList; if(!pDevice || !pDevice->pfnZCL) { ++gZclReportDeviceIndex; continue; } /* Find if any attribute are a asynchronous, then update the attribute */ do { for(i=0; i<pDevice->reportCount; ++i) { zclAttrDef_t *pAttrDef; zclReportAttr_t *pCurrentReportList = &pReportList[i]; /* only looking for this one cluster, to see if it's in the reportinglist */ if(!IsEqual2Bytes(pCurrentReportList->aClusterId, pDevice->pClusterDef[gAsynchronousClusterIndex].aClusterId)) continue; // If the cluster is on the reporting list, find the reporting attribute pAttrDef = ZCL_FindAttr(&pDevice->pClusterDef[gAsynchronousClusterIndex], pCurrentReportList->attrId); if(pAttrDef) { /* It's a asynchronous attribute, update before reporting */ if(ZclAttrIsAsynchronous_c(pAttrDef->flags)) { ++gAsynchronousClusterIndex; BeeAppUpdateDevice(0, gZclUI_SendReportingAttributeRequest_c, pAttrDef->id, pCurrentReportList->aClusterId, NULL); //Free the message, because we return from here MSG_Free(pMsg); return; } } } ++gAsynchronousClusterIndex; }while(gAsynchronousClusterIndex < pDevice->clusterCount); /* check each cluster for reporting attributes */ while(gZclReportClusterIndex < pDevice->clusterCount) { pCluster = &pDevice->pClusterDef[gZclReportClusterIndex]; pFrame = (void *)(&((uint8_t *)pMsg)[ApsmeGetAsduOffset()]); /* build the report for the next cluster */ reportLen = ZCL_BuildAttrReport( (zclCmdReportAttr_t *)(pFrame + 1), /* ptr to report frame */ pDevice, /* ptr to device */ pCluster ); /* no reporting attributes this cluster */ if(!reportLen) { ++gZclReportClusterIndex; continue; } /* set up the address info */ addrInfo.dstAddrMode = gZbAddrModeIndirect_c; addrInfo.srcEndPoint = endPointList[gZclReportDeviceIndex].pEndpointDesc->pSimpleDesc->endPoint; addrInfo.txOptions = gZclTxOptions; addrInfo.radiusCounter = afDefaultRadius_c; /* determine which cluster to send it to */ Copy2Bytes(addrInfo.aClusterId, pCluster->aClusterId); /* set up frame */ pFrame->frameControl = gZclFrameControl_FrameTypeGeneral | gZclFrameControl_DisableDefaultRsp; pFrame->transactionId = gZclTransactionId++; pFrame->command = gZclCmdReportAttr_c; /* send the report */ payloadLen = sizeof(zclFrame_t) + reportLen; (void)ZCL_DataRequestNoCopy(&addrInfo, payloadLen, pMsg); ++gZclReportClusterIndex; /* start a short timer between reporting clusters */ gfZclReportRestart = FALSE; ZLC_StartShortReportingTimer(); return; } /* try next device */ ++gZclReportDeviceIndex; gZclReportClusterIndex=0; gAsynchronousClusterIndex=0; } /* end of while(gZclReportDeviceIndex < gNum_EndPoints_c) */ if(pMsg) MSG_Free(pMsg); /* start up a new timer if needed */ if(gZclReportingSetup.reportTimeout != 0 && gZclReportingSetup.reportTimeout != 0xFFFF) { gZclReportingSetup.reportCounter = gZclReportingSetup.reportTimeout; ZLC_StartReportingTimer(); } }
/* SRV_NSetRequest ** ** Purpose: ** SRV_NSetRequest assists an application that wants to be an SCU of ** a number of SOP classes. This function constructs an N-SET-REQ ** message and sends it to the peer application which is acting as the ** SCP for a SOP class. This function waits for the response from the ** peer application and invokes the caller's callback function. ** ** The arguments to the callback function are: ** MSG_N_SET_REQ *setRequest ** MSG_N_SET_RESP *setResponse ** void *setCtx ** ** The first two arguments are MSG structures that contain the N-SET ** Request and N-SET Response messages respectively. The final ** argument is the caller's context variable that is passed to ** SRV_NSetRequest. ** ** The callback function should return SRV_NORMAL. Any other return ** value will cause the SRV facility to abort the Association. ** ** Parameter Dictionary: ** association The key which is used to access an existing ** association. ** params The list of parameters for the association. This ** list includes the list of presentation contexts. ** SOPClass UID of the SOP class used when the association was ** negotiated. Since this can be a meta class, it may ** not be the same as the class UID in the N-SET ** request message. ** setRequest Pointer to the structure with the N-SET request ** parameters. ** setResponse Pointer to caller's pointer to an N-SET response. ** This function will allocate an MSG_N_SET_RESP ** message and return the pointer to the caller. ** setCallback Address of user callback function to be called ** with the N-SET response from SCP. ** setCtx Pointer to user context information which will be ** passed to the callback function. Caller uses this ** variable to contain any context required for the ** callback function. ** dirName Name of directory where files may be created. ** ** ** Return Values: ** ** SRV_CALLBACKABORTEDSERVICE ** SRV_ILLEGALPARAMETER ** SRV_NOCALLBACK ** SRV_NORMAL ** SRV_OBJECTBUILDFAILED ** SRV_REQUESTFAILED ** SRV_UNEXPECTEDCOMMAND ** SRV_UNSUPPORTEDSERVICE ** ** Algorithm: ** Check if the callback function has been provided. ** Determine the presentation context ** Encode the N-SET request message as a command object and ** send it to an SCP ** Send data set, if one exists, to the SCP. ** Wait for a response message to arrive from the SCP ** Receive a data set, if one exists, from the SCP ** Return address of Response message structure to caller. ** ** Notes: ** The caller is responsible for explicitly setting the following ** fields in the N-SET request message: ** ** type ** messageID ** classUID ** dataSetType ** dataSet ** instanceUID ** ** The caller is also responsible for releasing the Response message ** structure after the SRV_NSetRequest function returns, ** using MSG_Free. */ CONDITION SRV_NSetRequest(DUL_ASSOCIATIONKEY ** association, DUL_ASSOCIATESERVICEPARAMETERS * params, char *SOPClass, MSG_N_SET_REQ * setRequest, MSG_N_SET_RESP * setResponse, SRV_N_SET_REQ_CALLBACK * setCallback, void *setCtx, char *dirName) { DCM_OBJECT * commandObject; /* Handle for a command object */ CONDITION cond; /* Return value from function calls */ DUL_PRESENTATIONCONTEXT * presentationCtx; /* Presentation context for this service */ DUL_PRESENTATIONCONTEXTID ctxID; void *message; MSG_TYPE messageType; MSG_N_SET_RESP * localResponse; unsigned short command; if (setCallback == NULL) return COND_PushCondition(SRV_NOCALLBACK, SRV_Message(SRV_NOCALLBACK), "SRV_NSetRequest"); presentationCtx = SRVPRV_PresentationContext(params, SOPClass); if (presentationCtx == NULL) return COND_PushCondition(SRV_UNSUPPORTEDSERVICE, SRV_Message(SRV_UNSUPPORTEDSERVICE), setRequest->classUID, "SRV_NSetRequest"); if (setRequest->type != MSG_K_N_SET_REQ) return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "type", "N-SET Request", "SRV_NSetRequest"); cond = MSG_BuildCommand(setRequest, &commandObject); if (cond != MSG_NORMAL) return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "N-SET Request", "SRV_NSetRequest"); cond = SRV_SendCommand(association, presentationCtx, &commandObject); (void) DCM_CloseObject(&commandObject); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_NSetRequest"); if (setRequest->dataSetType == DCM_CMDDATANULL) /* sending attribute list is mandatory */ return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "dataSetType", "N-SET Request", "SRV_NSetRequest"); cond = SRV_SendDataSet(association, presentationCtx, &setRequest->dataSet, NULL, NULL, 0); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_NSetRequest"); cond = SRV_ReceiveCommand(association, params, DUL_BLOCK, 0, &ctxID, &command, &messageType, &message); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_NSetRequest"); if (messageType != MSG_K_N_SET_RESP) { (void) MSG_Free(&message); return COND_PushCondition(SRV_UNEXPECTEDCOMMAND, SRV_Message(SRV_UNEXPECTEDCOMMAND), (int) command, "SRV_NSetRequest"); } localResponse = (MSG_N_SET_RESP *) message; if (localResponse->dataSetType == DCM_CMDDATANULL) { localResponse->dataSet = NULL; } else { cond = SRV_ReceiveDataSet(association, presentationCtx, DUL_BLOCK, 0, dirName, &localResponse->dataSet); if (cond != SRV_NORMAL) { (void) MSG_Free(&message); return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_NSetRequest"); } } cond = setCallback(setRequest, localResponse, setCtx); (void) MSG_Free(&message); if (localResponse->dataSet != NULL) { (void) DCM_CloseObject(&localResponse->dataSet); localResponse->dataSet = NULL; } if (setResponse != NULL) *setResponse = *localResponse; if (cond != SRV_NORMAL) return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_NSetRequest"); return SRV_NORMAL; }
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); }
/***************************************************************************** *Mac Application Task event processor. This function is called to * process all events for the task. Events include timers, messages and any * other user defined events * * Interface assumptions: None * * Return value: None *****************************************************************************/ void AppTask(event_t events) { /* Pointer for storing the messages from MLME, MCPS, and ASP. */ void *pMsgIn; /* Stores the status code returned by some functions. */ uint8_t rc; pMsgIn = NULL; /* Dequeue the MLME message */ if (events & gAppEvtMessageFromMLME_c) { /* Get the message from MLME */ pMsgIn = MSG_DeQueue(&mMlmeNwkInputQueue); /* Any time a beacon might arrive. Always handle the beacon frame first */ if (pMsgIn) { rc = App_WaitMsg(pMsgIn, gNwkBeaconNotifyInd_c); if(rc == errorNoError) { /* ALWAYS free the beacon frame contained in the beacon notify indication.*/ /* ALSO the application can use the beacon payload.*/ MSG_Free(((nwkMessage_t *)pMsgIn)->msgData.beaconNotifyInd.pBufferRoot); UartUtil_Print("Received an MLME-Beacon Notify Indication\n\r", gAllowToBlock_d); } } } /* The application state machine */ switch(gState) { case stateInit: /* Print a welcome message to the UART */ UartUtil_Print("MyWirelessApp Demo Non Beacon End Device application is initialized and ready.\n\r\n\r", gAllowToBlock_d); /* Goto Active Scan state. */ gState = stateScanActiveStart; TS_SendEvent(gAppTaskID_c, gAppEvtDummyEvent_c); break; case stateScanActiveStart: /* Start the Active scan, and goto wait for confirm state. */ UartUtil_Print("Start scanning for a PAN coordinator\n\r", gAllowToBlock_d); /*print a message on the LCD also*/ LCD_ClearDisplay(); LCD_WriteString(1,"Start scanning"); LCD_WriteString(2,"for coordinator"); rc = App_StartScan(gScanModeActive_c); if(rc == errorNoError) { gState = stateScanActiveWaitConfirm; } break; case stateScanActiveWaitConfirm: /* Stay in this state until the Scan confirm message arrives, and then goto the associate state. */ if (events & gAppEvtMessageFromMLME_c) { if (pMsgIn) { rc = App_WaitMsg(pMsgIn, gNwkScanCnf_c); if(rc == errorNoError) { rc = App_HandleScanActiveConfirm(pMsgIn); if(rc == errorNoError) { UartUtil_Print("Found a coordinator with the following properties:\n\r", gAllowToBlock_d); UartUtil_Print("----------------------------------------------------", gAllowToBlock_d); UartUtil_Print("\n\rAddress...........0x", gAllowToBlock_d); UartUtil_PrintHex(mCoordInfo.coordAddress, mCoordInfo.coordAddrMode == gAddrModeShort_c ? 2 : 8, 0); UartUtil_Print("\n\rPAN ID............0x", gAllowToBlock_d); UartUtil_PrintHex(mCoordInfo.coordPanId, 2, 0); UartUtil_Print("\n\rLogical Channel...0x", gAllowToBlock_d); UartUtil_PrintHex(&mCoordInfo.logicalChannel, 1, 0); UartUtil_Print("\n\rBeacon Spec.......0x", gAllowToBlock_d); UartUtil_PrintHex(mCoordInfo.superFrameSpec, 2, 0); UartUtil_Print("\n\rLink Quality......0x", gAllowToBlock_d); UartUtil_PrintHex(&mCoordInfo.linkQuality, 1, 0); UartUtil_Print("\n\r\n\r", gAllowToBlock_d); gState = stateAssociate; TS_SendEvent(gAppTaskID_c, gAppEvtDummyEvent_c); } else { UartUtil_Print("Scan did not find a suitable coordinator\n\r", gAllowToBlock_d); /*print a message on the LCD also*/ LCD_ClearDisplay(); LCD_WriteString(1,"No coordinator"); LCD_WriteString(2,"found."); } } } } break; case stateAssociate: /* Associate to the PAN coordinator */ UartUtil_Print("Associating to PAN coordinator on channel 0x", gAllowToBlock_d); UartUtil_PrintHex(&(mCoordInfo.logicalChannel), 1, gPrtHexNewLine_c); /*print a message on the LCD also*/ LCD_ClearDisplay(); LCD_WriteString(1,"Associating to "); LCD_WriteString(2,"PAN coordinator"); rc = App_SendAssociateRequest(); if(rc == errorNoError) gState = stateAssociateWaitConfirm; break; case stateAssociateWaitConfirm: /* Stay in this state until the Associate confirm message arrives, and then goto the Listen state. */ if (events & gAppEvtMessageFromMLME_c) { if (pMsgIn) { rc = App_WaitMsg(pMsgIn, gNwkAssociateCnf_c); if(rc == errorNoError) { rc = App_HandleAssociateConfirm(pMsgIn); if (rc == errorNoError) { UartUtil_Print("Successfully associated with the coordinator.\n\r", gAllowToBlock_d); UartUtil_Print("We were assigned the short address 0x", gAllowToBlock_d); UartUtil_PrintHex(maMyAddress, mAddrMode == gAddrModeShort_c ? 2 : 8, 0); UartUtil_Print("\n\r\n\rReady to send and receive data over the UART.\n\r\n\r", gAllowToBlock_d); /*print a message on the LCD also*/ LCD_ClearDisplay(); LCD_WriteString(1,"Ready to send"); LCD_WriteString(2,"and receive data"); /* Startup the timer */ TMR_StartSingleShotTimer(mTimer_c, mPollInterval, AppPollWaitTimeout); /* Go to the listen state */ gState = stateListen; TS_SendEvent(gAppTaskID_c, gAppEvtDummyEvent_c); } else { UartUtil_Print("\n\rAssociate Confirm wasn't successful... \n\r\n\r", gAllowToBlock_d); gState = stateScanActiveStart; TS_SendEvent(gAppTaskID_c, gAppEvtDummyEvent_c); } } } } break; case stateListen: //WSNProject //need to sleep? PWR_AllowDeviceToSleep(); Reason=PWR_EnterLowPower(); /* Transmit to coordinator data received from UART. */ if (events & gAppEvtMessageFromMLME_c) { if (pMsgIn) { /* Process it */ rc = App_HandleMlmeInput(pMsgIn); } } if (events & gAppEvtRxFromUart_c) { /* get byte from UART */ App_TransmitUartData(); } break; } if (pMsgIn) { /* Messages must always be freed. */ MSG_Free(pMsgIn); } /* Handle MCPS confirms and transmit data from UART */ if (events & gAppEvtMessageFromMCPS_c) { /* Get the message from MCPS */ pMsgIn = MSG_DeQueue(&mMcpsNwkInputQueue); if (pMsgIn) { /* Process it */ App_HandleMcpsInput(pMsgIn); /* Messages from the MCPS must always be freed. */ MSG_Free(pMsgIn); } } /* Check for pending messages in the Queue */ if(MSG_Pending(&mMcpsNwkInputQueue)) TS_SendEvent(gAppTaskID_c, gAppEvtMessageFromMCPS_c); if(MSG_Pending(&mMlmeNwkInputQueue)) TS_SendEvent(gAppTaskID_c, gAppEvtMessageFromMLME_c); }
CONDITION SRV_CStoreResponse(DUL_ASSOCIATIONKEY ** association, DUL_PRESENTATIONCONTEXT * ctx, MSG_C_STORE_REQ ** storeRequest, MSG_C_STORE_RESP * storeReply, char *fileName, SRV_C_STORE_RESP_CALLBACK * callback, void *callbackCtx, char *dirName) { int fd, done; unsigned long total, estimatedSize, nextCallback; unsigned short sendStatus = 0x0000; DUL_PDV pdv; CONDITION cond; DCM_OBJECT * object; DCM_FILE_META fileMeta; int storeAsPart10 = 0; char* paramValue; storeReply->messageIDRespondedTo = (*storeRequest)->messageID; storeReply->type = MSG_K_C_STORE_RESP; (void) strcpy(storeReply->classUID, (*storeRequest)->classUID); (void) strcpy(storeReply->instanceUID, (*storeRequest)->instanceUID); storeReply->conditionalFields = MSG_K_C_STORERESP_CLASSUID | MSG_K_C_STORERESP_INSTANCEUID; storeReply->dataSetType = DCM_CMDDATANULL; if (strlen(fileName) == 0 || fileName == NULL) { fd = -1; }else{ #ifdef _MSC_VER fd = _open(fileName, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, _S_IREAD | _S_IWRITE); #else fd = open(fileName, O_CREAT | O_WRONLY | O_TRUNC, 0666); #endif if (fd < 0) (void) COND_PushCondition(SRV_FILECREATEFAILED, SRV_Message(SRV_FILECREATEFAILED), fileName, "SRV_CStoreResponse"); } if (strcmp(ctx->acceptedTransferSyntax, DICOM_TRANSFERLITTLEENDIAN) != 0){ storeAsPart10 = 1; }else{ paramValue = UTL_GetConfigParameter("STORAGE/PART10FLAG"); if (paramValue != NULL) { if (strcmp(paramValue, "1") == 0) storeAsPart10 = 1; } } if ((storeAsPart10 == 1) && (fd > 0)){ int localStatus = 0; memset(&fileMeta, 0, sizeof(fileMeta)); setFileMeta(&fileMeta, *storeRequest, ctx->acceptedTransferSyntax); localStatus = writePart10MetaHeader(fd, &fileMeta); if (localStatus != 0) fd = -1; } if (fd < 0) { sendStatus = MSG_K_C_STORE_OUTOFRESOURCES; storeReply->conditionalFields |= MSG_K_C_STORERESP_ERRORCOMMENT; strcpy(storeReply->errorComment, "Storage Service unable to create local file"); fprintf(stderr,"Storage Service unable to create local file\n"); } done = 0; total = 0; estimatedSize = genericImageSize((*storeRequest)->classUID); nextCallback = estimatedSize / 10; while (!done) { cond = SRVPRV_ReadNextPDV(association, DUL_BLOCK, 0, &pdv); if (cond != SRV_NORMAL) { (void) MSG_Free((void **) storeRequest); return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CStoreResponse"); } if (pdv.pdvType != DUL_DATASETPDV) { (void) MSG_Free((void **) storeRequest); return COND_PushCondition(SRV_UNEXPECTEDPDVTYPE, SRV_Message(SRV_UNEXPECTEDPDVTYPE), (int) pdv.pdvType, "SRV_CStoreResponse"); } if (sendStatus == 0) if (write(fd, pdv.data, pdv.fragmentLength) != (int) pdv.fragmentLength) sendStatus = MSG_K_C_STORE_OUTOFRESOURCES; total += pdv.fragmentLength; if (pdv.lastPDV) done++; if (total > nextCallback){ cond = callback(*storeRequest, NULL, total, estimatedSize, NULL, callbackCtx, ctx); if (cond != SRV_NORMAL){ (void) MSG_Free((void **) storeRequest); return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CStoreResponse"); } nextCallback += estimatedSize / 10; } } if (fd >= 0) (void) close(fd); storeReply->status = sendStatus; if (sendStatus == 0x0000) { unsigned long options = DCM_ORDERLITTLEENDIAN; if (storeAsPart10 == 1) options = DCM_PART10FILE; cond = DCM_OpenFile(fileName, options, &object); if (cond != DCM_NORMAL) { (void) MSG_Free((void **) storeRequest); return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CStoreResponse"); } cond = callback(*storeRequest, storeReply, total, estimatedSize, &object, callbackCtx, ctx); if (cond != SRV_NORMAL) { (void) DCM_CloseObject(&object); return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CStoreResponse"); } (void) DCM_CloseObject(&object); } (void) MSG_Free((void **) storeRequest); cond = MSG_BuildCommand(storeReply, &object); if (cond != MSG_NORMAL) return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "STORE Request", "SRV_CStoreResponse"); cond = SRV_SendCommand(association, ctx, &object); (void) DCM_CloseObject(&object); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_RESPONSEFAILED, SRV_Message(SRV_RESPONSEFAILED), "SRV_CStoreResponse"); return SRV_NORMAL; }
CONDITION SRV_CStoreRequest(DUL_ASSOCIATIONKEY ** association, DUL_ASSOCIATESERVICEPARAMETERS * params, MSG_C_STORE_REQ * storeRequest, MSG_C_STORE_RESP * storeResponse, SRV_C_STORE_REQ_CALLBACK * callback, void *callbackCtx, char *dirName) { DCM_OBJECT * commandObject, /* Handle for a command object */ *dataSetObject; /* Handle for a Data Set object */ CONDITION cond; /* Return value from function calls */ DUL_PRESENTATIONCONTEXT * presentationCtx; /* Presentation context for this service */ DUL_PRESENTATIONCONTEXTID ctxID; void *message; MSG_TYPE messageType; unsigned long objectSize; unsigned short command; STORAGE_CTX localCtx; MSG_C_STORE_RESP * response; localCtx.callback = callback; localCtx.storeRequest = storeRequest; localCtx.storeResponse = NULL; localCtx.userCtx = callbackCtx; if (callback == NULL) return COND_PushCondition(SRV_NOCALLBACK, SRV_Message(SRV_NOCALLBACK), "SRV_CStoreRequest"); if (storeRequest->type != MSG_K_C_STORE_REQ) return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "type", "STORE Request", "SRV_CStoreRequest"); if (storeRequest->dataSetType == DCM_CMDDATANULL) return COND_PushCondition(SRV_ILLEGALPARAMETER, SRV_Message(SRV_ILLEGALPARAMETER), "dataSetType", "STORE Request", "SRV_CStoreRequest"); presentationCtx = SRVPRV_PresentationContext(params, storeRequest->classUID); if (presentationCtx == NULL) return COND_PushCondition(SRV_NOSERVICEINASSOCIATION, SRV_Message(SRV_NOSERVICEINASSOCIATION), storeRequest->classUID, "SRV_CStoreRequest"); cond = MSG_BuildCommand(storeRequest, &commandObject); if (cond != MSG_NORMAL) return COND_PushCondition(SRV_OBJECTBUILDFAILED, SRV_Message(SRV_OBJECTBUILDFAILED), "STORE Request", "SRV_CStoreRequest"); dataSetObject = storeRequest->dataSet; if (dataSetObject == NULL) { cond = DCM_OpenFile(storeRequest->fileName, DCM_ORDERLITTLEENDIAN, &dataSetObject); if (cond != DCM_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CStoreRequest"); } cond = DCM_GetObjectSize(&dataSetObject, &objectSize); if (cond != DCM_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CStoreRequest"); cond = SRV_SendCommand(association, presentationCtx, &commandObject); (void) DCM_CloseObject(&commandObject); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CStoreRequest"); cond = callback(storeRequest, NULL, 0, objectSize, callbackCtx); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CStoreRequest"); cond = SRV_SendDataSet(association, presentationCtx, &dataSetObject, localCallback, &localCtx, objectSize); if (storeRequest->dataSet == NULL) (void) DCM_CloseObject(&dataSetObject); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CStoreRequest"); cond = SRV_ReceiveCommand(association, params, DUL_BLOCK, 0, &ctxID, &command, &messageType, &message); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_REQUESTFAILED, SRV_Message(SRV_REQUESTFAILED), "SRV_CStoreRequest"); if (messageType != MSG_K_C_STORE_RESP) { (void) MSG_Free(&message); return COND_PushCondition(SRV_UNEXPECTEDCOMMAND, SRV_Message(SRV_UNEXPECTEDCOMMAND), (int) command, "SRV_CStoreRequest"); } response = (MSG_C_STORE_RESP *) message; if (storeResponse != NULL) *storeResponse = *response; cond = callback(storeRequest, response, objectSize, objectSize, callbackCtx); (void) MSG_Free(&message); if (cond != SRV_NORMAL) return COND_PushCondition(SRV_CALLBACKABORTEDSERVICE, SRV_Message(SRV_CALLBACKABORTEDSERVICE), "SRV_CStoreRequest"); return SRV_NORMAL; }
void ZDO_NwkManager ( nlmeZdoMessage_t *pZdoMsg /*IN: Message received from ZDO*/ ) { nlmeJoinIndication_t *pJoinIndication; uint8_t aNwkAddr[2]; (void)aNwkAddr; gMemoryFreedByApplication = FALSE; switch (pZdoMsg->msgType) { /************************************************************************************* NLME-Formation.confirm: Formation confirm is only available for PAN Coordinator devices or combo devices acting like coordinator. **************************************************************************************/ case gNlmeNetworkFormationConfirm_c: #if ( gCoordinatorCapability_d || gComboDeviceCapability_d) #if gComboDeviceCapability_d /* If a combo device is not acting like a PAN Coordinator should not do any further processing. */ if (NlmeGetRequest(gDevType_c) != gCoordinator_c) { break; } #endif /* Send an event to the ZDO state machine informing the fromation status. */ if (pZdoMsg->msgData.networkFormationConf.status == gZbSuccess_c) { ZDO_SendEvent(gZdoEvent_FormationSuccess_c); } else { ZDO_SendEvent(gZdoEvent_FormationFailure_c); } #endif break; /************************************************************************************* NLME-Discovery.confirm **************************************************************************************/ case gNlmeNetworkDiscoveryConfirm_c: /* If the device is trying to associate it self to a PAN, the state machine changes to be on gZdoDiscoveringNetworksState_c. */ if (ZDO_GetState() == gZdoDiscoveringNetworksState_c) { ZdoEvent_t event; /* The discovery information have already been stored by the NWK layer. Free up the confirm. */ if(pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor != NULL) { MSG_Free( pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor ); } /* send an event to state machine task depending on the confirmation */ event = (pZdoMsg->msgData.networkDiscoveryConf.status == gZbSuccess_c)? gZdoEvent_DiscoverySuccess_c : gZdoEvent_DiscoveryFailure_c; ZDO_SendEvent(event); /* Setting this variable to FALSE means that ZDO will free the message and not the application. */ gMemoryFreedByApplication = FALSE; break; } /*********************************************************************************** For any of this cases the tables does not need to be arround so lets free up the memory. IMPORTANT: The tables need to be freed to avoid memory leaks. ************************************************************************************/ NWK_FreeUpDiscoveryTables(); /* If the device is on running state this means that it may be the application the one commanding the discovery. */ if(ZDO_IsRunningState()) { /* Reprot the discovery information to hte application. */ ( void ) ZDP_APP_SapHandler((zdpToAppMessage_t *)pZdoMsg); /* Setting this variable to TRUE means that the application is responsible of freeing the list inside the discovery message. */ gMemoryFreedByApplication = TRUE; } /* Management commands prevent the ZDO stae machine for doing anything but finishing the process of the remote command. */ else if (ZDO_GetState() == gZdoRemoteCommandsState_c) { #if gMgmt_NWK_Disc_rsp_d /* Generate the response through zdpmanager */ Zdp_Mgmt_Send_Nwk_disc_conf( pZdoMsg ); #endif ZDO_SendEvent(gZdoEvent_ManagementResponse_c); /* The information was copied in ZDP so the list inside the packet is no longer needed. */ if (pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor != NULL) { MSG_Free( pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor ); } /* Setting this variable to FALSE means that all the buffers are free, no need to re-free it. */ gMemoryFreedByApplication = FALSE; } else { /* Clean up the discovery tables in the stack */ NWK_FreeUpDiscoveryTables(); if (pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor != NULL) { MSG_Free( pZdoMsg->msgData.networkDiscoveryConf.pNetworkDescriptor ); } gMemoryFreedByApplication = FALSE; } break; /************************************************************************************* NLME-Join.confirm: We have join TO SOME ONE. **************************************************************************************/ case gNlmeJoinConfirm_c: #if gRouterCapability_d || gEndDevCapability_d || gComboDeviceCapability_d /* Make sure that the discovery tables have been freed after join request has been processed. */ NWK_FreeUpDiscoveryTables(); /* If a combo device is not router or end device should not proceed. */ #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gCoordinator_c) { break; } #endif /* If the device is already on running state the node may receive the unsolicited rejoin response because of and addressconflict, so ignore the join confirm. */ if (ZDO_IsRunningState()) break; /* If the device is not running then force it to parse the confirm. */ ZDO_SetState(gZdoJoiningState_c); /* Send an event to the ZDO state machine informing about the joining state. */ if( pZdoMsg->msgData.joinConf.status == gZbSuccess_c ) { ZDO_SendEvent(gZdoEvent_JoinSuccess_c); } else { ZDO_SendEvent(gZdoEvent_JoinFailure_c); } #endif break; /************************************************************************************* NLME-Join.indication: A device has join TO US. **************************************************************************************/ case gNlmeJoinIndication_c: /* Do the casting for the message one time and in one place, Code saving. */ pJoinIndication = &pZdoMsg->msgData.joinIndication; /* To avoid reject packets when the node join and comunicate multi ple times, the devices should flush the APS Duplicate table. */ APS_RemoveEntryFromApsDuplicateTable(pJoinIndication->aShortAddress); /* Every child joined to us must be record, to avoid lossing it in case of reset. */ ZdoNwkMng_SaveToNvm(zdoNvmObject_NeighborTable_c); #if gRnplusCapability_d #if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) != gEndDevice_c) #endif { /* Remove the old routes to the joining device */ RemoveRouteEntry(pJoinIndication->aShortAddress); } #endif #endif #if gStandardSecurity_d || gHighSecurity_d /* If the joining device is associated from scratch erase previous data. */ if (pJoinIndication->rejoinNetwork == gAssociationJoin_c) { if (ApsmeGetRequest(gApsDefaultTCKeyType_c) == gTrustCenterLinkKey_c) { APS_ResetDeviceCounters(pJoinIndication->aExtendedAddress); } else { APS_RemoveSecurityMaterialEntry(pJoinIndication->aExtendedAddress); } /* Setting the last parameter to TRUE will erase APS secure material */ ZDO_SecClearDeviceData(pJoinIndication->aShortAddress, pJoinIndication->aExtendedAddress, FALSE); } /* If security is active and the joining mode is other that association join, no further processing should be done to the join indication. Consider the unsecure join. */ //else if ((pJoinIndication->rejoinNetwork == gNwkRejoin_c) && pJoinIndication->secureRejoin) //{ /* Make sure the memory will be freed */ //gMemoryFreedByApplication = FALSE; /* Do not process it further, no transport key will be needed. */ //return; //} else if (pJoinIndication->rejoinNetwork == gNwkRejoin_c && !pJoinIndication->secureRejoin) { /* Reset the Incoming frame counter of the dev that has left. */ /* Setting the last parameter to TRUE will erase APS secure material */ if (ApsmeGetRequest(gApsDefaultTCKeyType_c) == gTrustCenterLinkKey_c) { APS_ResetDeviceCounters(pJoinIndication->aExtendedAddress); } else { APS_RemoveSecurityMaterialEntry(pJoinIndication->aExtendedAddress); } /* Setting the last parameter to TRUE will erase APS secure material */ ZDO_SecClearDeviceData(pJoinIndication->aShortAddress, pJoinIndication->aExtendedAddress, FALSE); } /* The device must be set as Unauthenticated child in the NT. */ SSP_NwkSetRelationship(pJoinIndication->aExtendedAddress, gUnAuthenticatedChild_c); /* Keep the buffer around to be use in the state machine or the application. */ gMemoryFreedByApplication = TRUE; /*************************************************** Trust center specific join indication processing. ****************************************************/ #if gTrustCenter_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (gTrustCenter) #endif { /* Keep the information, we are going to start the joining state machine. */ MSG_Queue(&gJoinIndicationQueue, pZdoMsg); /* Tell the ZDO Task that we got a joining device packet and ready for action. */ TS_SendEvent(gZdoTaskID_c, gJoinIndicationArrive_c); } #endif #if !gTrustCenter_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (!gTrustCenter) #endif { uint8_t joiningType; bool_t isHighSecurity = FALSE; /* Every other device with joining capabilities should report the joining, using an APSME-UPDATE-DEVICE.request. */ isHighSecurity = (pJoinIndication->capabilityInformation & gSecurityCapability_c)? TRUE : FALSE; if (pJoinIndication->rejoinNetwork == gAssociationJoin_c) { joiningType = (isHighSecurity)? gHighSecurityDeviceUnsecuredJoin_c : gStandardDeviceUnsecuredJoin_c; } else if (pJoinIndication->rejoinNetwork == gNwkRejoin_c) { if (pJoinIndication->secureRejoin) { joiningType = (isHighSecurity)? gHighSecurityDeviceSecuredReJoin_c : gStandardDeviceSecuredReJoin_c; } else { joiningType = (isHighSecurity)? gHighSecurityDeviceUnsecuredRejoin_c : gStandardDeviceUnsecuredRejoin_c; } } // Always send the update device ZDO_APSME_Update_Device_request(pJoinIndication->aExtendedAddress, pJoinIndication->aShortAddress, joiningType, pJoinIndication->secureRejoin); (void)ZDP_APP_SapHandler((void *)pZdoMsg); } #endif /* #endif gStandardSecurity_d */ #endif break; /*break for join indication*/ /************************************************************************************* NLME-StartRouter.confirm: Every time that a Coordinator or a Router starts, genrates a start router confirm. **************************************************************************************/ case gNlmeStartRouterConfirm_c: #if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d /* Combo devices acting like ZED don't need this confirm. */ #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gEndDevice_c) { break; } #endif /* Indicate router has started (or not) */ if (pZdoMsg->msgData.startRouterConf.status == gZbSuccess_c) { ZDO_SendEvent(gZdoEvent_StartRouterSuccess_c); } else { ZDO_SendEvent(gZdoEvent_StartRouterFailure_c); } #endif break; /************************************************************************************* NLME-Sync.confirm **************************************************************************************/ case gNlmeSyncConfirm_c: #if gEndDevCapability_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) != gEndDevice_c) { break; } #endif pZdoMsg->msgType = gSyncConf_c; ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg ); /* The application is responsible of freen the buffers. */ gMemoryFreedByApplication = TRUE; #endif break; /************************************************************************************* NLME-PermitJoining.confirm **************************************************************************************/ case gNlmePermitJoiningConfirm_c: #if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gEndDevice_c) { break; } #endif if(ZDO_IsRunningState()) { /* let application know about the permit join */ pZdoMsg->msgType = gPermitjoinConf_c; ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg ); /* indicate this SAP handler won't be freeing the memory */ gMemoryFreedByApplication = TRUE; } #endif break; /************************************************************************************* NLME-DirectJoin.confirm **************************************************************************************/ case gNlmeDirectJoinConfirm_c: #if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gEndDevice_c) { break; } #endif /* The may come because the network layer start the direct join and the confirm must be pass up to the application. */ if (ZDO_IsRunningState()) { /* Send message on to app. Tell this SAP handler not to free it. */ (void) ZDP_APP_SapHandler( (void *)pZdoMsg ); gMemoryFreedByApplication = TRUE; } else if (ZDO_GetState() == gZdoRemoteCommandsState_c) { ZDO_SendEvent(gZdoEvent_ManagementResponse_c); #if gMgmt_Direct_Join_rsp_d && (gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d) #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gEndDevice_c) { break; } #endif /* Generate the response through zdpmanager */ Zdp_Mgmt_Direct_Join_conf( pZdoMsg ); /* Update the global variable to free the menory */ gMemoryFreedByApplication = TRUE; #endif } #endif break; /************************************************************************************* NLME-Leave.indication **************************************************************************************/ case gNlmeLeaveIndication_c: /* The local node is the one leaving the network. */ if (Cmp8BytesToZero(pZdoMsg->msgData.leaveIndication.aDeviceAddress)) { /* Only important to the local leave. Pick an appropiated leaving event. */ ZdoStopMode_t stopMode; /* Send event to ZDO state machine to initiate the reset procedure (r11, p272, ln31) The devices should not set the default mode to stop the node on a leave indication, the default mode send another leave.... and we just left. */ stopMode = gZdoStopModeDefault_c | gZdoStopMode; if (pZdoMsg->msgData.leaveIndication.rejoin) { /* We will come back.! */ stopMode |= gZdoStopMode_StopAndRestart_c; /* We are doing rejoin, we should not clear the tables. */ stopMode &= ~gZdoStopMode_ResetTables_c; } /* End of if (pZdoMsg->msgData.leaveIndication.rejoin) */ /* Tell ZDO to pull the breaks; */ ZDO_StopEx(stopMode); break; } /* End of if (Cmp8BytesToZero(pZdoMsg->msgData.leaveIndication.aDeviceAddress)) */ /* If we got the indiction and we are waiting for it, return to previous state. */ if (ZDO_GetState() == gZdoRemoteCommandsState_c) { ZDO_SendEvent(gZdoEvent_ManagementResponse_c); } #if gStandardSecurity_d || gHighSecurity_d #if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gEndDevice_c) { break; } #endif /* Reset the Incoming frame counter of the dev that has left. */ SSP_NwkResetDeviceFrameCounter( pZdoMsg->msgData.leaveIndication.aDeviceAddress ); /* If the device is Link capable remove the link key information if it exists. */ APS_RemoveSecurityMaterialEntry(pZdoMsg->msgData.leaveIndication.aDeviceAddress); /* Let the trust center know about the leaving device. */ // if (!IsSelfIeeeAddress(ApsmeGetRequest(gApsTrustCenterAddress_c))) #if !gTrustCenter_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (!gTrustCenter) #endif { ZDO_APSME_Update_Device_request(pZdoMsg->msgData.leaveIndication.aDeviceAddress, APS_GetNwkAddress(pZdoMsg->msgData.leaveIndication.aDeviceAddress, aNwkAddr), gDeviceLeft_c, 0x00); } #endif #endif #endif /* ZEDs dont porcess the removing of the children and removing of the routes. */ #if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gEndDevice_c) { break; } #endif #if gRnplusCapability_d /* Remove the old routes for the leaving device */ RemoveRouteEntry(APS_GetNwkAddress(pZdoMsg->msgData.leaveIndication.aDeviceAddress, aNwkAddr)); #endif /* Clean up address map if there is no bindings referencing address map entry consider deleting all bindings first. */ (void)APS_RemoveDeviceFromAddressMap(pZdoMsg->msgData.leaveIndication.aDeviceAddress); /* Tells the network layer to remove the leaving device from its tables. */ NWK_RemoveChildRecords(pZdoMsg->msgData.leaveIndication.aDeviceAddress); #endif /* Save the network data, to preserve that the leaving device is gone. Plus the counters for security (NWK and APS)that got reset. */ ZdoNwkMng_SaveToNvm(zdoNvmObject_All_c); break; /************************************************************************************* NLME-Leave.confirm **************************************************************************************/ case gNlmeLeaveConfirm_c: /* If we have received a management leave request, send the response */ if (ZDO_GetState() == gZdoRemoteCommandsState_c) { #if gMgmt_Leave_rsp_d Zdp_Mgmt_Send_leave_conf(pZdoMsg); /* The momery has been handled by the next higher layer. */ gMemoryFreedByApplication = TRUE; #endif ZDO_SendEvent(gZdoEvent_ManagementResponse_c); } /* The local node is the one leaving the network. */ if (Cmp8BytesToZero(pZdoMsg->msgData.leaveConf.aDeviceAddress)) { /* The self leave is handle in the indication. */ break; } #if gStandardSecurity_d || gHighSecurity_d #if gCoordinatorCapability_d || gRouterCapability_d || gComboDeviceCapability_d #if gComboDeviceCapability_d if (NlmeGetRequest(gDevType_c) == gEndDevice_c) { break; } #endif /* Reset the Incoming frame counter of the dev that has left. */ SSP_NwkResetDeviceFrameCounter( pZdoMsg->msgData.leaveIndication.aDeviceAddress ); /* If the device is Link capable remove the link key information if it exists. */ APS_RemoveSecurityMaterialEntry(pZdoMsg->msgData.leaveIndication.aDeviceAddress); /* Let the trust center know about the leaving device. */ ZDO_APSME_Update_Device_request(pZdoMsg->msgData.leaveIndication.aDeviceAddress, APS_GetNwkAddress(pZdoMsg->msgData.leaveIndication.aDeviceAddress, aNwkAddr), gDeviceLeft_c, 0x00); /* Tells the network layer to remove the leaving device from its tables. */ NWK_RemoveChildRecords(pZdoMsg->msgData.leaveIndication.aDeviceAddress); #endif /* #endif gStandardSecurity_d */ #endif break; /************************************************************************************* NLME-RouteDiscovery.confirm **************************************************************************************/ case gNlmeNetworkStatusCnf_c: case gNlmeRouteDiscoveryCnf_c: /* This packet will be freed by the application*/ gMemoryFreedByApplication = TRUE; /* Pass the packet to the App */ ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg ); break; /************************************************************************************* NLME-EnergyScan.confirm: An Energy Scan Confirm has come back. Was it due to the forming process, or due to FA/ZDP. **************************************************************************************/ case gNlmeEnergyScanConfirm_c: if(ZDO_GetState() == gZdoDiscoveringNetworksState_c) { if (pZdoMsg->msgData.EnergyScanConf.status == gZbSuccess_c) { ZDO_SendEvent(gZdoEvent_EnergyScanComplete_c); } else { ZDO_StopEx(gZdoStopModeDefault_c); } } /* Send to application layer */ ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg ); /* Update the global variable to free the memory */ gMemoryFreedByApplication = TRUE; break; case gNlmeNetworkStatusInd_c: case gNlmeTxReport_c: /* Send to application layer */ ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg ); /* Update the global variable to free the memory */ gMemoryFreedByApplication = TRUE; break; case gNwkProcessFrameConf_c: #if gStandardSecurity_d || gHighSecurity_d /* Send to application layer */ ( void ) ZDP_APP_SapHandler( (void *)pZdoMsg ); /* Update the global variable to free the memory */ gMemoryFreedByApplication = TRUE; #else gMemoryFreedByApplication = FALSE; #endif break; default: break; } /* End of switch */ }