Загрузка данных
#include <assert.h>
#include <string.h>
#include "fsl_common.h"
#include "srtm_auto_service.h"
#include "srtm_heap.h"
#include "srtm_list.h"
#include "srtm_dispatcher.h"
#include "srtm_service.h"
#include "srtm_service_struct.h"
#include "srtm_channel.h"
#include "srtm_channel_struct.h"
#include "srtm_peercore.h"
#include "srtm_peercore_struct.h"
#include "srtm_message.h"
#include "srtm_message_struct.h"
#include "srtm_mutex.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Protocol definition */
#define SRTM_AUTO_CATEGORY (0x8U)
#define SRTM_AUTO_VERSION (0x0100U)
#define SRTM_AUTO_RETURN_CODE_SUCEESS (0x0U)
#define SRTM_AUTO_RETURN_CODE_FAIL (0x1U)
#define SRTM_AUTO_RETURN_CODE_UNSUPPORTED (0x2U)
/* Auto Service Notification Command definition */
/* Auto event register */
typedef struct _srtm_auto_client
{
srtm_list_t node;
srtm_channel_t channel;
uint32_t clientId;
} *srtm_auto_client_t;
/* Service handle */
typedef struct _srtm_auto_service
{
struct _srtm_service service;
srtm_auto_adapter_t vehicle;
srtm_list_t clients;
} *srtm_auto_service_t;
typedef enum _srtm_auto_async_req_state
{
SRTM_AUTO_ASYNC_REQ_STATE_INIT = 0U, /* State before request sent. */
SRTM_AUTO_ASYNC_REQ_STATE_WAITING, /* Waiting for the result */
SRTM_AUTO_ASYNC_REQ_STATE_CANCELLED, /* Request cancelled */
SRTM_AUTO_ASYNC_REQ_STATE_FINISHED /* Got result. */
} srtm_auto_async_req_state_t;
SRTM_ANON_DEC_BEGIN
typedef struct _srtm_auto_async_req
{
bool syncResult; /* Whether return result in sync/async way. */
srtm_mutex_t mutex;
srtm_sem_t sem;
srtm_service_t service;
uint8_t retCode;
uint32_t cmdParamLen;
union
{
uint8_t *result;
srtm_auto_cmd_cb_t resultCb;
};
union
{
uint32_t resultLen;
void *resultCbParam;
};
srtm_auto_async_req_state_t reqState;
} *srtm_auto_async_req_t;
SRTM_ANON_DEC_END
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
static void SRTM_AutoService_DestroyAsyncReq(srtm_auto_async_req_t req)
{
if (req->mutex)
{
SRTM_Mutex_Destroy(req->mutex);
}
if (req->sem)
{
SRTM_Sem_Destroy(req->sem);
}
SRTM_Heap_Free(req);
}
static srtm_auto_async_req_t SRTM_AutoService_CreateAsyncReq(srtm_service_t service)
{
srtm_auto_async_req_t req;
req = (srtm_auto_async_req_t)SRTM_Heap_Malloc(sizeof(struct _srtm_auto_async_req));
if (req)
{
(void)memset(req, 0, sizeof(struct _srtm_auto_async_req));
req->mutex = SRTM_Mutex_Create();
req->sem = SRTM_Sem_Create(1, 0);
if (!req->mutex || !req->sem)
{
SRTM_AutoService_DestroyAsyncReq(req);
req = NULL;
}
else
{
req->service = service;
}
}
return req;
}
static srtm_status_t SRTM_AutoService_Register(srtm_service_t service,
srtm_channel_t channel,
uint32_t clientId,
uint8_t *reqData,
uint32_t reqLen,
uint8_t *respData,
uint32_t respLen)
{
srtm_auto_service_t handle = (srtm_auto_service_t)service;
srtm_auto_adapter_t vehicle = handle->vehicle;
srtm_auto_client_t client;
srtm_list_t *list;
srtm_status_t status = SRTM_Status_Success;
/* First find out if client already registered */
for (list = handle->clients.next; list != &handle->clients; list = list->next)
{
client = SRTM_LIST_OBJ(srtm_auto_client_t, node, list);
if (client->channel == channel && client->clientId == clientId)
{
break;
}
}
if (list == &handle->clients)
{
/* Not found */
client = (srtm_auto_client_t)SRTM_Heap_Malloc(sizeof(struct _srtm_auto_client));
if (!client)
{
status = SRTM_Status_OutOfMemory;
}
else
{
/* Notify application that there's a new client registered */
assert(vehicle->registerEvent);
status = vehicle->registerEvent(vehicle, clientId, reqData, reqLen, respData, respLen);
if (status != SRTM_Status_Success)
{
SRTM_Heap_Free(client);
}
else
{
client->channel = channel;
client->clientId = clientId;
SRTM_List_AddTail(&handle->clients, &client->node);
}
}
}
else
{
SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: already registered\r\n", __func__);
status = SRTM_Status_Error;
}
return status;
}
static srtm_status_t SRTM_AutoService_Unregister(srtm_service_t service,
srtm_channel_t channel,
uint32_t clientId,
uint8_t *reqData,
uint32_t reqLen,
uint8_t *respData,
uint32_t respLen)
{
srtm_auto_service_t handle = (srtm_auto_service_t)service;
srtm_auto_adapter_t vehicle = handle->vehicle;
srtm_auto_client_t client;
srtm_list_t *list;
srtm_status_t status = SRTM_Status_Success;
/* First find out if client already registered */
for (list = handle->clients.next; list != &handle->clients; list = list->next)
{
client = SRTM_LIST_OBJ(srtm_auto_client_t, node, list);
if (client->channel == channel && client->clientId == clientId)
{
break;
}
}
if (list == &handle->clients)
{
/* Not found */
status = SRTM_Status_Error;
}
else
{
/* Notify application that there's a client unregistered */
assert(vehicle->unregisterEvent);
status = vehicle->unregisterEvent(vehicle, clientId, reqData, reqLen, respData, respLen);
if (status == SRTM_Status_Success)
{
SRTM_List_Remove(&client->node);
SRTM_Heap_Free(client);
}
}
return status;
}
static srtm_status_t SRTM_AutoService_Event(srtm_service_t service,
srtm_channel_t channel,
uint8_t command,
uint32_t clientId,
uint8_t *reqData,
uint32_t reqLen,
uint8_t *respData,
uint32_t respLen)
{
srtm_auto_service_t handle = (srtm_auto_service_t)service;
srtm_auto_adapter_t vehicle = handle->vehicle;
srtm_auto_client_t client;
srtm_list_t *list;
srtm_status_t status = SRTM_Status_Success;
/* First find out if client already registered */
for (list = handle->clients.next; list != &handle->clients; list = list->next)
{
client = SRTM_LIST_OBJ(srtm_auto_client_t, node, list);
if (client->channel == channel && client->clientId == clientId)
{
break;
}
}
if (list == &handle->clients)
{
/* Not found */
SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s(%d): client %d is not registered\r\n", __func__, command,
clientId);
status = SRTM_Status_Error;
}
else
{
switch (command)
{
case SRTM_AUTO_CMD_CONTROL:
assert(vehicle->control);
status = vehicle->control(vehicle, clientId, reqData, reqLen, respData, respLen);
break;
case SRTM_AUTO_CMD_POWER_REPORT:
assert(vehicle->powerReport);
status = vehicle->powerReport(vehicle, clientId, reqData, reqLen, respData, respLen);
break;
case SRTM_AUTO_CMD_GET_INFO:
assert(vehicle->getInfo);
status = vehicle->getInfo(vehicle, clientId, reqData, reqLen, respData, respLen);
break;
default:
SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: command %d unsupported!\r\n", __func__, command);
status = SRTM_Status_Error;
break;
}
}
return status;
}
/* Both request and notify are called from SRTM dispatcher context */
static srtm_status_t SRTM_AutoService_Request(srtm_service_t service, srtm_request_t request)
{
srtm_status_t status;
srtm_channel_t channel;
uint8_t command;
uint32_t payloadLen;
srtm_response_t response;
struct _srtm_auto_payload *autoReq;
struct _srtm_auto_payload *autoResp;
assert(service->dispatcher);
SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s\r\n", __func__);
channel = SRTM_CommMessage_GetChannel(request);
command = SRTM_CommMessage_GetCommand(request);
autoReq = (struct _srtm_auto_payload *)SRTM_CommMessage_GetPayload(request);
payloadLen = SRTM_CommMessage_GetPayloadLen(request);
response = SRTM_Response_Create(channel, SRTM_AUTO_CATEGORY, SRTM_AUTO_VERSION, command,
sizeof(struct _srtm_auto_payload));
if (!response)
{
return SRTM_Status_OutOfMemory;
}
autoResp = (struct _srtm_auto_payload *)SRTM_CommMessage_GetPayload(response);
status = SRTM_Service_CheckVersion(service, request, SRTM_AUTO_VERSION);
if (status != SRTM_Status_Success || !autoReq || payloadLen != sizeof(struct _srtm_auto_payload))
{
SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: format error!\r\n", __func__);
autoResp->clientId = autoReq ? autoReq->clientId : 0;
autoResp->retCode = SRTM_AUTO_RETURN_CODE_UNSUPPORTED;
}
else
{
autoResp->clientId = autoReq->clientId;
SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO,
"SRTM receive request:client=%d, cmd=%x, data0=%x,data1=%x,data2=%x!\r\n", autoReq->clientId,
command, autoReq->data[0], autoReq->data[1], autoReq->data[2]);
switch (command)
{
case SRTM_AUTO_CMD_REGISTER:
status = SRTM_AutoService_Register(service, channel, autoReq->clientId, autoReq->data,
SRTM_USER_DATA_LENGTH, autoResp->data, SRTM_USER_DATA_LENGTH);
autoResp->retCode =
status == SRTM_Status_Success ? SRTM_AUTO_RETURN_CODE_SUCEESS : SRTM_AUTO_RETURN_CODE_FAIL;
break;
case SRTM_AUTO_CMD_UNREGISTER:
status = SRTM_AutoService_Unregister(service, channel, autoReq->clientId, autoReq->data,
SRTM_USER_DATA_LENGTH, autoResp->data, SRTM_USER_DATA_LENGTH);
autoResp->retCode =
status == SRTM_Status_Success ? SRTM_AUTO_RETURN_CODE_SUCEESS : SRTM_AUTO_RETURN_CODE_FAIL;
break;
default:
status = SRTM_AutoService_Event(service, channel, command, autoReq->clientId, autoReq->data,
SRTM_USER_DATA_LENGTH, autoResp->data, SRTM_USER_DATA_LENGTH);
autoResp->retCode =
status == SRTM_Status_Success ? SRTM_AUTO_RETURN_CODE_SUCEESS : SRTM_AUTO_RETURN_CODE_FAIL;
break;
}
}
return SRTM_Dispatcher_DeliverResponse(service->dispatcher, response);
}