/* Maximus project {{{ * * Copyright (C) 2012 MStar Semiconductor * * <<>> * * }}} */ /** * \file maximus/interface/msg/src/MsgFunctionCall.cpp * \ingroup maximus_interface_msg * */ #include "maximus/interface/msg/inc/MsgFunctionCall.h" #include "maximus/interface/inc/Maximus.h" #include "maximus/interface/station/inc/Station.h" #include "maximus/processors/inc/FunctionCallProcessor.h" #include "maximus/processors/inc/SystemProcessor.h" #include "maximus/interface/msg/inc/templates.h" #include "maximus/utils/inc/Error.h" #include "maximus/utils/inc/Logger.h" #include #include namespace bp = boost::python; Function_Call_Msg_Id MsgFunctionCall::msg_id = 0; MsgFunctionCall::MsgFunctionCall (Maximus &ref1, const std::string &name): interface (ref1), mResponseReceived (false), is_async_msg (false), rx_msg_id (0), function_name (name), sta_id (0) { logFunction (); msg_id ++; } MsgFunctionCall::~MsgFunctionCall () { logFunction (); clear_list_of_parameters (); } inline void MsgFunctionCall::clear_list_of_parameters () { while (!parameter_list.empty ()) { delete (parameter_list.back ()); parameter_list.pop_back (); } } void MsgFunctionCall::add_param_empty ( const std::string & name) { logFunction (); parameter_list.push_back ( new FunctionCallParameter (name, 0, NULL)); } void MsgFunctionCall::add_param_string ( const std::string &name, const std::string &value) { logFunction (); parameter_list.push_back ( new FunctionCallParameter ( name, value.length () + 1, (unsigned char *) value.c_str ())); } void MsgFunctionCall::add_param_bool ( const std::string &name, const bool &value) { logFunction (); unsigned char temp[1] = { value }; parameter_list.push_back ( new FunctionCallParameter ( name, sizeof (temp), temp)); } void MsgFunctionCall::add_param_1 ( const std::string &name, const unsigned char &value) { logFunction (); unsigned char temp[1] = { value }; parameter_list.push_back ( new FunctionCallParameter ( name, sizeof (temp), temp)); } void MsgFunctionCall::add_param_2 ( const std::string &name, const unsigned short &value) { logFunction (); unsigned char temp[2] = { (unsigned char) (value >> 8), (unsigned char) value, }; parameter_list.push_back ( new FunctionCallParameter ( name, sizeof (temp), temp)); } void MsgFunctionCall::add_param_4 ( const std::string &name, const unsigned long &value) { logFunction (); unsigned char temp[4] = { (unsigned char) (value >> 24), (unsigned char) (value >> 16), (unsigned char) (value >> 8), (unsigned char) (value), }; parameter_list.push_back ( new FunctionCallParameter ( name, sizeof (temp), temp)); } void MsgFunctionCall::add_param_8 ( const std::string &name, const unsigned long long &value) { logFunction (); uint32_t high = value >> 32; uint32_t low = value; unsigned char temp[sizeof (long long)] = { (unsigned char) (low >> 24), (unsigned char) (low >> 16), (unsigned char) (low >> 8), (unsigned char) (low), (unsigned char) (high >> 24), (unsigned char) (high >> 16), (unsigned char) (high >> 8), (unsigned char) (high), }; parameter_list.push_back ( new FunctionCallParameter ( name, sizeof (temp), temp)); } void MsgFunctionCall::add_param_table_1 ( const std::string &name, const bp::tuple &value) { logFunction (); uint size = len (value); unsigned char temp[size]; for (uint i = 0; i < size; i++) { /* Network format. */ temp[i] = bp::extract (value[i]); } parameter_list.push_back ( new FunctionCallParameter ( name, sizeof (temp), temp)); } void MsgFunctionCall::add_param_table_2 ( const std::string &name, const bp::tuple &value) { logFunction (); uint size = len (value); unsigned char temp[size * sizeof (short)]; uint idx; unsigned short val; for (uint i = 0; i < size; i++) { idx = i * sizeof (short); val = bp::extract (value[i]); /* Network format. */ temp[idx+0] = (unsigned char) (val >> 8); temp[idx+1] = (unsigned char) (val); } parameter_list.push_back ( new FunctionCallParameter ( name, sizeof (temp), temp)); } void MsgFunctionCall::add_param_table_4 ( const std::string &name, const bp::tuple &value) { logFunction (); uint size = len (value); unsigned char temp[size * sizeof (long)]; uint idx; unsigned long val; for (uint i = 0; i < size; i++) { idx = i * sizeof (long); val = bp::extract (value[i]); /* Network format. */ temp[idx+0] = (unsigned char) (val >> 24); temp[idx+1] = (unsigned char) (val >> 16); temp[idx+2] = (unsigned char) (val >> 8); temp[idx+3] = (unsigned char) (val); } parameter_list.push_back ( new FunctionCallParameter ( name, sizeof (temp), temp)); } bool MsgFunctionCall::removeParameter (const std::string & name) { logFunction (); bool bRemoveParameter = false; static ParametersList::iterator it; for (it = parameter_list.begin(); it != parameter_list.end(); ++it) { if ( !(*it)->getName().compare(name) ) { parameter_list.erase (it); bRemoveParameter = true; break; } } return bRemoveParameter; } void MsgFunctionCall::remove_param (const std::string & name) { logFunction (); removeParameter (name); } void MsgFunctionCall::set_cb ( bp::object user_cb) { logFunction (); mCallback = user_cb; } void MsgFunctionCall::remove_cb () { logFunction (); mCallback = cb_t (); } void MsgFunctionCall::set_sta (const Station &sta) { logFunction (); sta_id = sta.getStationId (); } void MsgFunctionCall::send_async_2 (const Station &sta) { logFunction(); set_sta (sta); send_async (); } MsgFunctionCall * MsgFunctionCall::send_2 (const Station &sta) { set_sta (sta); return send (); } void MsgFunctionCall::send_async () { logFunction (); is_async_msg = true; while (!interface.is_station_idle (sta_id)) interface.process (); interface.get_functioncall ()->sendMsg ( *this, boost::bind (&MsgFunctionCall::receive_response, this, _1)); /* XXX & TODO : It's cleary a patch. * This part must be rewrite ! */ clear_list_of_parameters (); } MsgFunctionCall * MsgFunctionCall::send () { logFunction (); // Register callback and send message while (!interface.is_station_idle (sta_id)) interface.process (); interface.get_functioncall ()->sendMsg ( *this, boost::bind (&MsgFunctionCall::receive_response, this, _1)); /* XXX & TODO : It's clearly a patch. * This part must be rewrite ! */ clear_list_of_parameters (); while (!mResponseReceived) interface.process(); mResponseReceived = false; if (mCallback) { (mCallback) (boost::ref(*this)); /* Free python dependency. */ mCallback = cb_t (); } return this; } bool MsgFunctionCall::is_param (const std::string &name) const { logFunction (); bool bIsParam; /* max size of 1 parameter */ unsigned long length = FUNCTION_CALL_PARAM_MAX_SIZE; unsigned char *pParam = new unsigned char [length]; bIsParam = (NULL != bind_param (name, length, pParam)); delete [] pParam; return bIsParam; } unsigned char * MsgFunctionCall::bind_param ( const std::string & name, unsigned long & length, unsigned char * p_data) const { logFunction (); /* parameter not found => return NULL. */ unsigned char * pData = NULL; if (bindParameter (name, length, p_data)) { // Parameter found => return p_data pData = p_data; } return pData; } bool MsgFunctionCall::bindParameter ( const std::string name_of_parameter_to_get, unsigned long & data_length, unsigned char * p_data ) const { logFunction (); ParametersList::const_iterator it; bool bBindParameter = false; for (it = parameter_list.begin (); it != parameter_list.end (); ++it) { if (!(*it)->getName ().compare (name_of_parameter_to_get) ) { bBindParameter = true; if (data_length < (*it)->getValueLength()) { maximus_log (LOG_WARNING, "bind_param: parameter value length too small to get the parameter value"); maximus_log (LOG_WARNING, " (given data length = " << data_length << " and needed data length = " << (*it)->getValueLength() << ")"); maximus_log (LOG_WARNING, " => parameter value will be cut"); } else if (data_length > (*it)->getValueLength()) { maximus_log (LOG_WARNING, "bind_param: parameter value length too large to get the parameter value"); maximus_log (LOG_WARNING, " => update length from " << data_length << " to " << (*it)->getValueLength()); data_length = (*it)->getValueLength(); } if ( (NULL != (*it)->getValue()) && (NULL != p_data) ) { memcpy (p_data, (*it)->getValue(), data_length); break; } } } return bBindParameter; } Function_Call_Msg_Id MsgFunctionCall::get_tx_msg_id ( ) const { return msg_id; } Function_Call_Msg_Id MsgFunctionCall::get_rx_msg_id ( ) const { return rx_msg_id; } void MsgFunctionCall::receive_response ( const FunctionSciMsg & function_sci_msg ) { logFunction (); /********************** * XXX: TODO: PATCH * **********************/ unsigned char *p_data; unsigned int data_length; Function_Call_Msg_Id msg_id_rx; Function_Call_Parameters_Number param_nb; function_sci_msg.patch_to_get_data ( &p_data, &data_length, &msg_id_rx, ¶m_nb); /****************** * End of PATCH * ******************/ Function_Call_Parameters_Number i; rx_msg_id = msg_id_rx; unsigned char *p_current_data = p_data;; function_name.assign ((char *)p_current_data); p_current_data += function_name.size () + 1; for (i = 0; i < param_nb; i++) { FunctionCallParameter *param_i = new FunctionCallParameter; std::string temp; temp.assign ((char *)p_current_data); param_i->setName (temp); p_current_data += temp.size () + 1; uint16_t tempLength = (static_cast (*p_current_data) << 8) + static_cast (*(p_current_data + 1)); if (FUNCTION_CALL_PARAM_MAX_SIZE < tempLength) { maximus_log (LOG_ERROR, "length of parameter value exceeds max size!"); errno = EMSGSIZE; throw Error (__PRETTY_FUNCTION__, "Length of parameter value exceeds max size", errno); } param_i->setValueLength (tempLength); p_current_data += 2; param_i->setValue (p_current_data); p_current_data += tempLength; /* Add parameter to the parameters list of the * received function SCI msg. */ parameter_list.push_back (param_i); } mResponseReceived = true; if (is_async_msg && mCallback) { (mCallback) (boost::ref(*this)); /* Free python dependency. */ mCallback = cb_t (); } } std::string MsgFunctionCall::bind_param_1 ( const std::string name) { std::string str; unsigned long ulLength = FUNCTION_CALL_PARAM_MAX_SIZE; unsigned char ucValue[ulLength]; if (NULL != MsgFunctionCall::bind_param (name, ulLength, ucValue)) { str.assign((char *)ucValue, ulLength); } return str; } std::string MsgFunctionCall::bind_param_string ( const std::string name) { std::string str (bind_param_1 (name)); if ((0 < str.length()) && ('\0' == str[str.length()-1]) ) { str.erase(str.length()-1); } return str; } bool MsgFunctionCall::bind_param_bool ( const std::string name) { return MsgFunctionCall::bind_param(name); } unsigned short int MsgFunctionCall::bind_param_ushort ( const std::string name) { return MsgFunctionCall::bind_param (name); } unsigned long int MsgFunctionCall::bind_param_ulong ( const std::string name) { return MsgFunctionCall::bind_param (name); } unsigned long long MsgFunctionCall::bind_param_ull ( const std::string name) { return MsgFunctionCall::bind_param (name); } bp::tuple MsgFunctionCall::bind_param_n_u8 ( const std::string name) { bp::tuple t = bp::make_tuple (); std::string str (bind_param_1 (name)); for (unsigned int n=0; n < str.length (); n += sizeof (uint8_t)) { t += bp::make_tuple ((uint8_t)str[n]); } return t; } bp::tuple MsgFunctionCall::bind_param_n_u16 ( const std::string name) { bp::tuple t = bp::make_tuple (); std::string str (bind_param_1 (name)); for (unsigned int n = 0; n