/* Cesar project {{{ * * Copyright (C) 2007 Spidcom * * <<>> * * }}} */ /** * \file fcall_param.c * \brief The 'function call' parameters management functions * \ingroup host * * This file provides 'function call' parameters management functions * * \todo */ #include "common/std.h" #include #include #include #include "host/fcall.h" #ifndef UNIT_TEST #include "lib/swap.h" #include "host/syscall.h" #else /* UNIT_TEST */ #include #include #endif /* UNIT_TEST */ /** * init the parameter table to add new paramters inside the message * \param param pointer to param context * \param id string id of parameters' function * \param msg_id id of fcall message to process asynchronous calls * \return 0 if ok, -1 if failed with errno= * - EINVAL if fcall or id is NULL * - ENAMETOOLONG if id length >= FUNCTION_CALL_ID_MAX_SIZE */ int fcall_param_init(fcall_param_t *param, char *id, unsigned short msg_id) { DBG_ASSERT(param); DBG_ASSERT(id); if((param == NULL) || (id == NULL)) { errno = EINVAL; return -1; } memset(param, '\0', sizeof(fcall_param_t)); /* check id length */ if(id != NULL) { if(strlen(id) >= FUNCTION_CALL_ID_MAX_SIZE) { errno = ENAMETOOLONG; return -1; } /* get the function id */ strcpy(param->id, id); } param->msg_id = msg_id; return 0; } /** * reset the parameter table and buffer to add new paramters inside the message * function id, msg id and is_async stay unmodified * \param param pointer to param context * \return 0 if ok, -1 if failed with errno= * - EINVAL if fcall is NULL */ int fcall_param_reset(fcall_param_t *param) { int i; DBG_ASSERT(param); if(param == NULL) { errno = EINVAL; return -1; } param->param_nb = 0; for(i = 0; i < FUNCTION_CALL_PARAM_MAX_NB; i++) { param->param_table[i].id = NULL; } return 0; } /** * find a parameter according to its id and bind it into a user variable * \param param pointer to param context * \param msg sci message containing the parameters * \param id identifier of wanted parameter as string format * \param max_length maximum length of receiving data area * \param data pointer to data area where to put the found parameter * \return actual length of binded data if ok, -1 if failed with errno= * - EINVAL if param, id or data is NULL * - ENOENT if id has not been found into parameter context */ int fcall_param_bind(fcall_param_t *param, sci_msg_t *msg, char *id, unsigned int max_length, void *data) { int index; unsigned int length; DBG_ASSERT(param); DBG_ASSERT(msg); DBG_ASSERT(id); DBG_ASSERT(data); if((param == NULL) || (msg == NULL) || (id == NULL) || (data == NULL)) { errno = EINVAL; return -1; } DBG_ASSERT(max_length); if(max_length == 0) { errno = EINVAL; return -1; } /* check param_nb validity */ if(param->param_nb > FUNCTION_CALL_PARAM_MAX_NB) param->param_nb = FUNCTION_CALL_PARAM_MAX_NB; else if(param->param_nb <= 0) { errno = ENOENT; return -1; } /* get the wanted index */ for(index = 0; index < param->param_nb; index++) { if(!strcmp(param->param_table[index].id, id)) { /* found id */ /* get length */ length = ntohs(*param->param_table[index].length); /* check the maximum available length */ if(length > max_length) length = max_length; /* copy data into user buffer */ if(length > 0) memcpy(data, param->param_table[index].data, length); break; } } if(index >= param->param_nb) { /* not found */ errno = ENOENT; return -1; } return length; } /** * add a new parameter element into the parameter context * \param param pointer to param context where to add new parameter * \param msg pointer to sci message to add the paramter * \param id id of new parameter * \param length length of new parameter * \param data pointer to data of new added parameter * \return 0 if ok, -1 if failed with errno= * - EINVAL if param, id of data is NULL, or if length < 0 or > FUNCTION_CALL_PARAM_MAX_SIZE * - ENAMETOOLONG if id length >= FUNCTION_CALL_ID_MAX_SIZE * - ENOSPC if parameter nb is already FUNCTION_CALL_PARAM_MAX_NB */ int fcall_param_add(fcall_param_t *param, sci_msg_t *msg, char *id, int length, void *data) { int total_len; DBG_ASSERT(param); DBG_ASSERT(msg); DBG_ASSERT(id); DBG_ASSERT(strlen(id)); DBG_ASSERT(length >= 0); DBG_ASSERT(length <= FUNCTION_CALL_PARAM_MAX_SIZE); DBG_ASSERT((length <= 0) || (data != NULL)); if((param == NULL) || (msg == NULL) || (id == NULL) || (strlen(id) == 0) || (length < 0) || (length > FUNCTION_CALL_PARAM_MAX_SIZE) || ((length > 0) && (data == NULL))) { errno = EINVAL; return -1; } /* check id length */ if(strlen(id) >= FUNCTION_CALL_ID_MAX_SIZE) { errno = ENAMETOOLONG; return -1; } /* check available free param */ if(param->param_nb >= FUNCTION_CALL_PARAM_MAX_NB) { errno = ENOSPC; return -1; } /* compute total data length to reserve */ total_len = strlen(id) + 1 + sizeof(uint16_t) + length; if(sci_msg_push(msg, total_len) < 0) return -1; /* copy id, length and data into msg and match the param structure */ param->param_table[param->param_nb].id = (char *)(msg->data_begin); strcpy(param->param_table[param->param_nb].id, id); param->param_table[param->param_nb].length = (unsigned short *)(param->param_table[param->param_nb].id + strlen(id) + 1); *param->param_table[param->param_nb].length = htons(length); param->param_table[param->param_nb].data = (unsigned char *)param->param_table[param->param_nb].length + sizeof(unsigned short); memcpy(param->param_table[param->param_nb].data, data, length); /* increment the parameter number */ param->param_nb++; return 0; } void fcall_param_dump(fcall_param_t *param, int fd, char *buffer, int size) { int i, j; buffer[size - 1] = '\0'; snprintf(buffer, size - 1, "fcall_param: id='%s', nb=%d\n", param->id, param->param_nb); write(fd, buffer, strlen(buffer)); for(i = 0; i < param->param_nb; i++) { snprintf(buffer, size - 1, " id=%s, length=%d, data=", param->param_table[i].id, ntohs(*param->param_table[i].length)); write(fd, buffer, strlen(buffer)); for(j = 0; j < ntohs(*param->param_table[i].length); j++) { snprintf(buffer, size - 1, "%02x-", param->param_table[i].data[j]); write(fd, buffer, 3); } write(fd, "\n", 1); } }