summaryrefslogtreecommitdiff
path: root/cesar/cp/msg/src
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/cp/msg/src')
-rw-r--r--cesar/cp/msg/src/cm/conn/msg_cm_conn_info_cnf.c17
-rw-r--r--cesar/cp/msg/src/cm/conn/msg_cm_conn_info_req.c17
-rw-r--r--cesar/cp/msg/src/cm/conn/msg_cm_conn_mod_cnf.c95
-rw-r--r--cesar/cp/msg/src/cm/conn/msg_cm_conn_mod_req.c85
-rw-r--r--cesar/cp/msg/src/cm/conn/msg_cm_conn_new_cnf.c110
-rw-r--r--cesar/cp/msg/src/cm/conn/msg_cm_conn_new_req.c91
-rw-r--r--cesar/cp/msg/src/cm/conn/msg_cm_conn_rel_ind.c92
-rw-r--r--cesar/cp/msg/src/cm/conn/msg_cm_conn_rel_rsp.c76
-rw-r--r--cesar/cp/msg/src/field/msg_field_cid.c70
-rw-r--r--cesar/cp/msg/src/field/msg_field_cinfo.c93
-rw-r--r--cesar/cp/msg/src/field/msg_field_classifier.c563
-rw-r--r--cesar/cp/msg/src/field/msg_field_cspec.c114
-rw-r--r--cesar/cp/msg/src/field/msg_field_qmp.c1189
-rw-r--r--cesar/cp/msg/src/msg.c336
-rw-r--r--cesar/cp/msg/src/msg_apcm.c16
-rw-r--r--cesar/cp/msg/src/msg_cc.c141
-rw-r--r--cesar/cp/msg/src/msg_cm.c273
-rw-r--r--cesar/cp/msg/src/msg_cm_convert.c65
-rw-r--r--cesar/cp/msg/src/msg_drv.c497
19 files changed, 3940 insertions, 0 deletions
diff --git a/cesar/cp/msg/src/cm/conn/msg_cm_conn_info_cnf.c b/cesar/cp/msg/src/cm/conn/msg_cm_conn_info_cnf.c
new file mode 100644
index 0000000000..1ccb86bc67
--- /dev/null
+++ b/cesar/cp/msg/src/cm/conn/msg_cm_conn_info_cnf.c
@@ -0,0 +1,17 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}}
+ * \file test_msg_cm_conn_rel_ind.c
+ * \brief This file provides management functions for message CM_CONN_INFO.CNF.
+ * \ingroup cp/msg
+ *
+ */
+
+
+#include "common/std.h"
+#include "cp/msg/inc/msg_cm.h"
+
diff --git a/cesar/cp/msg/src/cm/conn/msg_cm_conn_info_req.c b/cesar/cp/msg/src/cm/conn/msg_cm_conn_info_req.c
new file mode 100644
index 0000000000..be01371940
--- /dev/null
+++ b/cesar/cp/msg/src/cm/conn/msg_cm_conn_info_req.c
@@ -0,0 +1,17 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}}
+ * \file test_msg_cm_conn_rel_ind.c
+ * \brief This file provides management functions for message CM_CONN_INFO.REQ.
+ * \ingroup cp/msg
+ *
+ */
+
+
+#include "common/std.h"
+#include "cp/msg/inc/msg_cm.h"
+
diff --git a/cesar/cp/msg/src/cm/conn/msg_cm_conn_mod_cnf.c b/cesar/cp/msg/src/cm/conn/msg_cm_conn_mod_cnf.c
new file mode 100644
index 0000000000..267006eb47
--- /dev/null
+++ b/cesar/cp/msg/src/cm/conn/msg_cm_conn_mod_cnf.c
@@ -0,0 +1,95 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}}
+ * \file msg_cm_conn_mod_cnf.c
+ * \brief This file provides management functions for message CM_CONN_MOD.CNF.
+ * \ingroup cp/msg
+ *
+ */
+
+#include "common/std.h"
+#include "cp/msg/inc/msg_cm_conn.h"
+#include "cp/msg/inc/msg_field.h"
+
+
+
+/**
+ * Initialize the message CM_CONN_MOD_CNF
+ * \param msg Message to be initialized.
+ *
+ */
+void
+msg_cm_conn_mod_cnf_init(msg_cm_conn_mod_cnf_t* data)
+{
+ dbg_assert_ptr(data);
+
+ msg_field_cid_init(&(data->cid));
+ data->result = 0;
+ msg_field_cspec_init(&(data->proposed_cspec));
+
+ cp_dbg_msg_cm_conn_mod_cnf(*data);
+
+}
+
+
+
+/**
+ * Decode a CM_CONN_MOD_CNF message from a MME message.
+ * \param msg MME Message.
+ * \param data Structure where the data is saved.
+ *
+ */
+void
+msg_cm_conn_mod_cnf_set_on_mme_msg(msg_mme_t* msg, msg_cm_conn_mod_cnf_t* data)
+{
+ u8* local_stream = (u8*)msg->mm_entry;
+ len_t len;
+
+ dbg_assert_ptr(data);
+ cp_dbg_msg_cm_conn_mod_cnf(*data);
+ dbg_assert_ptr(msg);
+
+ len = msg_field_cid_set_on_stream( local_stream, &(data->cid));
+ local_stream += len;
+
+ *local_stream = data->result;
+ local_stream++;
+
+ if(data->result == CONN_MOD_FAILED)
+ msg_field_cspec_set_on_stream( local_stream, &(data->proposed_cspec));
+
+}
+
+
+/**
+ * Encode a CM_CONN_MOD_CNF message on a MME msg.
+ * \param msg MME message where the data is saved.
+ * \param data Data source.
+ *
+ */
+void
+msg_cm_conn_mod_cnf_get_from_mme_msg(msg_mme_t* msg, msg_cm_conn_mod_cnf_t* data)
+{
+ u8* local_stream = (u8*)msg->mm_entry;
+ len_t len;
+
+
+ dbg_assert_ptr(msg);
+ dbg_assert_ptr(data);
+
+ len = msg_field_cid_get_from_stream( local_stream, &(data->cid));
+ local_stream += len;
+
+ data->result = *local_stream;
+ local_stream ++;
+
+ if(data->result == CONN_MOD_FAILED)
+ msg_field_cspec_get_from_stream( local_stream, &(data->proposed_cspec));
+
+ cp_dbg_msg_cm_conn_mod_cnf(*data);
+}
+
diff --git a/cesar/cp/msg/src/cm/conn/msg_cm_conn_mod_req.c b/cesar/cp/msg/src/cm/conn/msg_cm_conn_mod_req.c
new file mode 100644
index 0000000000..b422464692
--- /dev/null
+++ b/cesar/cp/msg/src/cm/conn/msg_cm_conn_mod_req.c
@@ -0,0 +1,85 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}}
+ * \file msg_cm_conn_mod_req.c
+ * \brief This file provides management functions for message CM_CONN_MOD.REQ.
+ * \ingroup cp/msg
+ *
+ */
+
+#include "common/std.h"
+#include "cp/msg/inc/msg_cm_conn.h"
+#include "cp/msg/inc/msg_field.h"
+
+
+
+/**
+ * Initialize the message CM_CONN_MOD_REQ
+ * \param msg Message to be initialized.
+ *
+ */
+void
+msg_cm_conn_mod_req_init(msg_cm_conn_mod_req_t* data)
+{
+ dbg_assert_ptr(data);
+
+ msg_field_cid_init(&(data->cid));
+ msg_field_cspec_init(&(data->modified_cspec));
+
+ cp_dbg_msg_cm_conn_mod_req(*data);
+
+}
+
+
+
+/**
+ * Decode a CM_CONN_MOD_REQ message from a MME message.
+ * \param msg MME Message.
+ * \param data Structure where the data is saved.
+ *
+ */
+void
+msg_cm_conn_mod_req_set_on_mme_msg(msg_mme_t* msg, msg_cm_conn_mod_req_t* data)
+{
+ u8* local_stream = (u8*)msg->mm_entry;
+ len_t len;
+
+ dbg_assert_ptr(data);
+ cp_dbg_msg_cm_conn_mod_req(*data);
+ dbg_assert_ptr(msg);
+
+ len = msg_field_cid_set_on_stream( local_stream, &(data->cid));
+ local_stream += len;
+
+ msg_field_cspec_set_on_stream( local_stream, &(data->modified_cspec));
+
+}
+
+
+/**
+ * Encode a CM_CONN_MOD_REQ message on a MME msg.
+ * \param msg MME message where the data is saved.
+ * \param data Data source.
+ *
+ */
+void
+msg_cm_conn_mod_req_get_from_mme_msg(msg_mme_t* msg, msg_cm_conn_mod_req_t* data)
+{
+ u8* local_stream = (u8*)msg->mm_entry;
+ len_t len;
+
+ dbg_assert_ptr(msg);
+ dbg_assert_ptr(data);
+
+ len = msg_field_cid_get_from_stream( local_stream, &(data->cid));
+ local_stream += len;
+
+ msg_field_cspec_get_from_stream( local_stream, &(data->modified_cspec));
+
+ cp_dbg_msg_cm_conn_mod_req(*data);
+}
+
diff --git a/cesar/cp/msg/src/cm/conn/msg_cm_conn_new_cnf.c b/cesar/cp/msg/src/cm/conn/msg_cm_conn_new_cnf.c
new file mode 100644
index 0000000000..da2cc7b4a8
--- /dev/null
+++ b/cesar/cp/msg/src/cm/conn/msg_cm_conn_new_cnf.c
@@ -0,0 +1,110 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}}
+ * \file msg_cm_conn_new_cnf.c
+ * \brief This file provides management functions for message CM_CONN_NEW.CNF.
+ * \ingroup cp/msg
+ *
+ */
+
+#include "common/std.h"
+#include "cp/msg/inc/msg_cm_conn.h"
+#include "cp/msg/inc/msg_field.h"
+
+
+/**
+ * Initialize the message MSG_CM_CONN_NEW_CNF.
+ * \param msg Message to be initialized.
+ *
+ */
+void
+msg_cm_conn_new_cnf_init(msg_cm_conn_new_cnf_t* msg)
+{
+ dbg_assert_ptr(msg);
+
+ msg_field_cid_init(&(msg->cid));
+ msg->llid_r = 0;
+ msg->result = 0;
+ msg_field_cspec_init( &(msg->cspec_proposed));
+}
+
+
+
+/**
+ * Decode a CM_CONN_NEW_CNF message from a MME message.
+ * \param msg MME Message.
+ * \param data Structure where the data is saved.
+ *
+ */
+void
+msg_cm_conn_new_cnf_get_from_mme_msg(msg_mme_t* msg, msg_cm_conn_new_cnf_t* data)
+{
+ u8* local_stream = (u8*)msg->mm_entry;
+ len_t len;
+
+ dbg_assert_ptr(data);
+ dbg_assert_ptr(msg);
+
+ // get CID
+ len = msg_field_cid_get_from_stream(local_stream, &(data->cid));
+ local_stream += len;
+
+ // get LLID-R
+ data->llid_r = *local_stream;
+ local_stream ++;
+
+ // get Result
+ data->result = *local_stream;
+ local_stream ++;
+
+ if(data->result == CONN_FAILURE_OTHER)
+ {
+ // get CSPEC
+ msg_field_cspec_get_from_stream(local_stream, &(data->cspec_proposed));
+ }
+
+ cp_dbg_msg_cm_conn_new_cnf(*data);
+
+}
+
+
+/**
+ * Encode a CM_CONN_NEW_CNF message on a MME msg.
+ * \param msg MME message where the data is saved.
+ * \param data Data source.
+ *
+ */
+void
+msg_cm_conn_new_cnf_set_on_mme_msg(msg_mme_t* msg, msg_cm_conn_new_cnf_t* data)
+{
+ u8* local_stream = (u8*)msg->mm_entry;
+ len_t len;
+
+ dbg_assert_ptr(data);
+ cp_dbg_msg_cm_conn_new_cnf(*data);
+ dbg_assert_ptr(msg);
+
+
+ // set CID
+ len = msg_field_cid_set_on_stream(local_stream, &(data->cid));
+ local_stream += len;
+
+ // set LLID-R
+ *local_stream = data->llid_r ;
+ local_stream ++;
+
+ // set Result
+ *local_stream = data->result;
+ local_stream ++;
+
+ if (data->result == CONN_FAILURE_OTHER)
+ {
+ // set CSPEC
+ msg_field_cspec_set_on_stream(local_stream, &(data->cspec_proposed));
+ }
+
+}
diff --git a/cesar/cp/msg/src/cm/conn/msg_cm_conn_new_req.c b/cesar/cp/msg/src/cm/conn/msg_cm_conn_new_req.c
new file mode 100644
index 0000000000..abe38597ae
--- /dev/null
+++ b/cesar/cp/msg/src/cm/conn/msg_cm_conn_new_req.c
@@ -0,0 +1,91 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}}
+ * \file msg_cm_conn_new_req.c
+ * \brief This file provides management functions for message CM_CONN_NEW.REQ.
+ * \ingroup cp/msg
+ *
+ */
+
+#include "common/std.h"
+#include "cp/msg/inc/msg_cm_conn.h"
+
+
+/**
+ * Initialize the message CM_CONN_NEW_REQ
+ * \param msg Message to be initialized.
+ *
+ */
+void
+msg_cm_conn_new_req_init(msg_cm_conn_new_req_t* data)
+{
+ dbg_assert_ptr(data);
+
+ msg_field_cid_init( &(data->cid));
+ msg_field_classifier_init( &(data->classifier_rule));
+ msg_field_cspec_init( &(data->cspec));
+
+}
+
+/**
+ * Decode a CM_CONN_NEW_REQ message from a MME message.
+ * \param msg MME Message.
+ * \param data Structure where the data is saved.
+ *
+ */
+void
+msg_cm_conn_new_req_get_from_mme_msg(msg_mme_t* msg, msg_cm_conn_new_req_t* data)
+{
+ u8* local_stream = (u8*)msg->mm_entry;
+ len_t len;
+
+ dbg_assert_ptr(data);
+
+ dbg_assert_ptr(msg);
+
+ // get CID
+ len = msg_field_cid_get_from_stream(local_stream, &(data->cid));
+ local_stream += len;
+
+ // get CSPEC
+ len = msg_field_cspec_get_from_stream(local_stream, &(data->cspec));
+ local_stream += len;
+
+ // get classifier rules
+ msg_field_classifier_get_from_stream(local_stream, &(data->classifier_rule));
+
+ cp_dbg_msg_cm_conn_new_req( *data );
+}
+
+/**
+ * Encode a CM_CONN_NEW_REQ message on a MME msg.
+ * \param msg MME message where the data is saved.
+ * \param data Data source.
+ *
+ */
+void
+msg_cm_conn_new_req_set_on_mme_msg(msg_mme_t* msg, msg_cm_conn_new_req_t* data)
+{
+ u8* local_stream = (u8*)msg->mm_entry;
+ len_t len;
+
+ dbg_assert_ptr(data);
+ cp_dbg_msg_cm_conn_new_req( *data );
+ dbg_assert_ptr(msg);
+
+ // set CID
+ len = msg_field_cid_set_on_stream(local_stream, &(data->cid));
+ local_stream += len;
+
+ // set CSPEC
+ len = msg_field_cspec_set_on_stream(local_stream, &(data->cspec));
+ local_stream += len;
+
+ // set classifier rule
+ msg_field_classifier_set_on_stream( local_stream, &(data->classifier_rule));
+
+}
diff --git a/cesar/cp/msg/src/cm/conn/msg_cm_conn_rel_ind.c b/cesar/cp/msg/src/cm/conn/msg_cm_conn_rel_ind.c
new file mode 100644
index 0000000000..f06409c028
--- /dev/null
+++ b/cesar/cp/msg/src/cm/conn/msg_cm_conn_rel_ind.c
@@ -0,0 +1,92 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}}
+ * \file msg_cm_conn_rel_ind.c
+ * \brief This file provides management functions for message CM_CONN_NEW.REQ.
+ * \ingroup cp/msg
+ *
+ */
+
+#include "common/std.h"
+#include "cp/msg/inc/msg_cm_conn.h"
+
+
+/**
+ * Initialize the message CM_CONN_REL_IND
+ * \param msg Message to be initialized.
+ *
+ */
+void
+msg_cm_conn_rel_ind_init(msg_cm_conn_rel_ind_t* data)
+{
+ dbg_assert_ptr(data);
+
+ msg_field_cid_init(&(data->cid));
+ data->reason_code = 0;
+ msg_field_cspec_init( &(data->violated_cspec));
+}
+
+/**
+ * Decode a CM_CONN_REL_IND message from a MME message.
+ * \param msg MME Message.
+ * \param data Structure where the data is saved.
+ *
+ */
+void
+msg_cm_conn_rel_ind_get_from_mme_msg(msg_mme_t* msg, msg_cm_conn_rel_ind_t* data)
+{
+ u8* local_stream = (u8*)msg->mm_entry;
+ len_t len;
+
+ dbg_assert_ptr(data);
+ dbg_assert_ptr(msg);
+
+ // get CID
+ len = msg_field_cid_get_from_stream(local_stream, &(data->cid));
+ local_stream += len;
+
+ // get Reason Code
+ data->reason_code = *local_stream;
+ local_stream ++;
+
+ // get violated CSPEC
+ msg_field_cspec_get_from_stream(local_stream, &(data->violated_cspec));
+
+ cp_dbg_msg_cm_conn_rel_ind(*data);
+}
+
+
+/**
+ * Encode a CM_CONN_REL_IND message on a MME msg.
+ * \param msg MME message where the data is saved.
+ * \param data Data source.
+ *
+ */
+void
+msg_cm_conn_rel_ind_set_on_mme_msg(msg_mme_t* msg, msg_cm_conn_rel_ind_t* data)
+{
+ u8* local_stream = (u8*)msg->mm_entry;
+ len_t len;
+
+ dbg_assert_ptr(data);
+ cp_dbg_msg_cm_conn_rel_ind(*data);
+ dbg_assert_ptr(msg);
+
+ // set CID
+ len = msg_field_cid_set_on_stream(local_stream, &(data->cid));
+ local_stream += len;
+
+ // set Reason Code
+ *local_stream = data->reason_code;
+ local_stream ++;
+
+ // set violated CSPEC
+ msg_field_cspec_set_on_stream(local_stream, &(data->violated_cspec));
+
+}
+
+
diff --git a/cesar/cp/msg/src/cm/conn/msg_cm_conn_rel_rsp.c b/cesar/cp/msg/src/cm/conn/msg_cm_conn_rel_rsp.c
new file mode 100644
index 0000000000..e25f5017e8
--- /dev/null
+++ b/cesar/cp/msg/src/cm/conn/msg_cm_conn_rel_rsp.c
@@ -0,0 +1,76 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}}
+ * \file msg_cm_conn_new_rsp.c
+ * \brief This file provides management functions for message CM_CONN_NEW.RSP.
+ * \ingroup cp/msg
+ *
+ */
+
+#include "common/std.h"
+#include "cp/msg/inc/msg_cm_conn.h"
+#include "cp/msg/inc/msg_field.h"
+
+
+
+/**
+ * Initialize the message CM_CONN_REL_RSP
+ * \param msg Message to be initialized.
+ *
+ */
+void
+msg_cm_conn_rel_rsp_init(msg_cm_conn_rel_rsp_t* data)
+{
+ dbg_assert_ptr(data);
+
+ msg_field_cid_init(&(data->cid));
+
+ cp_dbg_msg_cm_conn_rel_rsp(*data);
+
+}
+
+
+
+/**
+ * Decode a CM_CONN_REL_RSP message from a MME message.
+ * \param msg MME Message.
+ * \param data Structure where the data is saved.
+ *
+ */
+void
+msg_cm_conn_rel_rsp_set_on_mme_msg(msg_mme_t* msg, msg_cm_conn_rel_rsp_t* data)
+{
+ u8* local_stream = (u8*)msg->mm_entry;
+
+ dbg_assert_ptr(data);
+ cp_dbg_msg_cm_conn_rel_rsp(*data);
+ dbg_assert_ptr(msg);
+
+ msg_field_cid_set_on_stream( local_stream, &(data->cid));
+
+}
+
+
+/**
+ * Encode a CM_CONN_REL_RSP message on a MME msg.
+ * \param msg MME message where the data is saved.
+ * \param data Data source.
+ *
+ */
+void
+msg_cm_conn_rel_rsp_get_from_mme_msg(msg_mme_t* msg, msg_cm_conn_rel_rsp_t* data)
+{
+ u8* local_stream = (u8*)msg->mm_entry;
+
+ dbg_assert_ptr(msg);
+ dbg_assert_ptr(data);
+
+ msg_field_cid_get_from_stream( local_stream, &(data->cid));
+
+ cp_dbg_msg_cm_conn_rel_rsp(*data);
+}
+
diff --git a/cesar/cp/msg/src/field/msg_field_cid.c b/cesar/cp/msg/src/field/msg_field_cid.c
new file mode 100644
index 0000000000..b893e1314c
--- /dev/null
+++ b/cesar/cp/msg/src/field/msg_field_cid.c
@@ -0,0 +1,70 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}}
+ * \file conn_msg_cid.c
+ * \brief This file provides management functions for CID (Connection Identifier) field.
+ * \ingroup cp/msg
+ *
+ */
+
+#include "common/std.h"
+#include "lib/swap.h"
+#include "cp/msg/inc/msg_cm_conn.h"
+
+
+/**
+ * Initialize a CID (Connection Identifier) structure.
+ * \param cid Pointer of the data to be initialized
+ *
+ */
+void
+msg_field_cid_init(cid_t* cid)
+{
+ *cid = 1;
+}
+
+
+
+/**
+ * Read the CID (Connection Identifier) from the stream and put the CID value
+ * on the cid pointer. The function returns the CID length.
+ *
+ * \param stream Data source contening the cid value.
+ * \param cid Pointer of the data to be modified.
+ * \return length of the CID field.
+ *
+ */
+len_t
+msg_field_cid_get_from_stream (u8* stream, cid_t * cid)
+{
+
+ dbg_assert_ptr (stream);
+ dbg_assert_ptr (cid);
+
+
+ *cid = ntohs(*(u16*)stream);
+
+ dbg_assert (*cid != 0);
+
+ return 2;
+}
+
+
+/**
+* Write the CID value on the stream. The function returns the data length written.
+*
+* param stream Data destination of the CID value.
+* param cid Pointer of the data to be written.
+* return Length of the data.
+*
+*/
+len_t
+msg_field_cid_set_on_stream(u8 * stream, cid_t* cid)
+{
+ *(u16*)stream = htons(*cid);
+ return 2;
+}
diff --git a/cesar/cp/msg/src/field/msg_field_cinfo.c b/cesar/cp/msg/src/field/msg_field_cinfo.c
new file mode 100644
index 0000000000..4407feb04a
--- /dev/null
+++ b/cesar/cp/msg/src/field/msg_field_cinfo.c
@@ -0,0 +1,93 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}}
+ * \file conn_msg_cinfo.c
+ * \brief This file provides management functions for CINFO (Connection Information) field.
+ * \ingroup cp/msg
+ *
+ */
+
+#include "common/std.h"
+#include "cp/msg/inc/msg_cm_conn.h"
+
+
+/**
+ * Initialize a CINFO structure.
+ * \param cinfo
+ *
+ */
+void
+msg_field_cinfo_init (cinfo_t* cinfo)
+{
+
+ bzero(cinfo, 5);
+
+}
+
+
+/**
+ * Read a CINFO structure on a stream. The function returns the length of the structure.
+ * \param stream Data source contening the CINFO structure.
+ * \param cinfo Pointer of the data destination.
+ * \return Length of the CINFO structure.
+ *
+ */
+len_t
+msg_field_cinfo_get_from_stream(u8 * stream, cinfo_t* cinfo)
+{
+
+ u8 * local_stream = stream;
+ len_t len;
+
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(cinfo);
+
+ cinfo->valid = *local_stream; local_stream++;
+
+ if (cinfo->valid == CINFO_VALID)
+ {
+ bcopy( local_stream, (u8*)(cinfo)+1, 4);
+ len = 5;
+ }
+ else // cinfo->valid == CINFO_NOT_VALID
+ {
+ len = 1;
+ }
+
+ cp_dbg_cinfo(*cinfo);
+
+ return len;
+}
+
+
+
+/**
+ * Write a CINFO structure on a stream. The function returns the length of the structure.
+ * \param stream Destination of the CINFO data.
+ * \param cinfo Source.
+ * \return Length of the data written.
+ *
+ */
+len_t
+msg_field_cinfo_set_on_stream(u8 * stream, cinfo_t* cinfo)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(cinfo);
+ cp_dbg_cinfo(*cinfo);
+
+ if (cinfo->valid == CINFO_VALID)
+ {
+ bcopy((u8*)cinfo, stream, 5);
+ return 5;
+ }
+ else // cinfo->valid == CINFO_NOT_VALID
+ {
+ bcopy( (u8*)cinfo, stream, 1);
+ return 1;
+ }
+
+}
diff --git a/cesar/cp/msg/src/field/msg_field_classifier.c b/cesar/cp/msg/src/field/msg_field_classifier.c
new file mode 100644
index 0000000000..90ccc065da
--- /dev/null
+++ b/cesar/cp/msg/src/field/msg_field_classifier.c
@@ -0,0 +1,563 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}}
+ * \file msg_field_classifier.c
+ * \brief This file provides management functions for classifier_rules field.
+ * \ingroup cp/msg
+ *
+ */
+
+#include "common/std.h"
+#include "lib/swap.h"
+#include "cp/msg/inc/msg_cm_conn.h"
+
+// Private functions declaration
+len_t msg_field_classifier_copy_rule_ethernet_destination_address_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_rule_ethernet_source_address_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_rule_vlan_user_priority_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_rule_vlan_id_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv4_type_of_service_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv4_protocol_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv4_source_address_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv4_destination_address_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv6_traffic_class_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv6_flow_label_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv6_source_address_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv6_destination_address_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_tcp_source_port_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_tcp_destination_port_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_udp_source_port_on_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_udp_destination_port_on_stream(u8* stream, classifier_rules_data_t* data);
+
+
+len_t msg_field_classifier_copy_rule_ethernet_destination_address_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_rule_ethernet_source_address_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_rule_vlan_user_priority_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_rule_vlan_id_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv4_type_of_service_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv4_protocol_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv4_source_address_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv4_destination_address_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv6_traffic_class_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv6_flow_label_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv6_source_address_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_ipv6_destination_address_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_tcp_source_port_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_tcp_destination_port_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_udp_source_port_from_stream(u8* stream, classifier_rules_data_t* data);
+len_t msg_field_classifier_copy_udp_destination_port_from_stream(u8* stream, classifier_rules_data_t* data);
+
+
+
+
+
+//////////////////////////////////////////////////////////////
+// Private Type
+
+#define NBR_CLASSIFIER_FIELD 16
+#define FILTER_FIRST_BIT 0x01
+
+typedef len_t ( *copy_classifier_t)(u8* stream, classifier_rules_data_t* data);
+
+copy_classifier_t copy_classifier_from_stream_tb[] =
+{
+ msg_field_classifier_copy_rule_ethernet_destination_address_from_stream,
+ msg_field_classifier_copy_rule_ethernet_source_address_from_stream,
+ msg_field_classifier_copy_rule_vlan_user_priority_from_stream,
+ msg_field_classifier_copy_rule_vlan_id_from_stream,
+ msg_field_classifier_copy_ipv4_type_of_service_from_stream,
+ msg_field_classifier_copy_ipv4_protocol_from_stream,
+ msg_field_classifier_copy_ipv4_source_address_from_stream,
+ msg_field_classifier_copy_ipv4_destination_address_from_stream,
+ msg_field_classifier_copy_ipv6_traffic_class_from_stream,
+ msg_field_classifier_copy_ipv6_flow_label_from_stream,
+ msg_field_classifier_copy_ipv6_source_address_from_stream,
+ msg_field_classifier_copy_ipv6_destination_address_from_stream,
+ msg_field_classifier_copy_tcp_source_port_from_stream,
+ msg_field_classifier_copy_tcp_destination_port_from_stream,
+ msg_field_classifier_copy_udp_source_port_from_stream,
+ msg_field_classifier_copy_udp_destination_port_from_stream
+};
+
+copy_classifier_t copy_classifier_on_stream_tb[] =
+{
+ msg_field_classifier_copy_rule_ethernet_destination_address_on_stream,
+ msg_field_classifier_copy_rule_ethernet_source_address_on_stream,
+ msg_field_classifier_copy_rule_vlan_user_priority_on_stream,
+ msg_field_classifier_copy_rule_vlan_id_on_stream,
+ msg_field_classifier_copy_ipv4_type_of_service_on_stream,
+ msg_field_classifier_copy_ipv4_protocol_on_stream,
+ msg_field_classifier_copy_ipv4_source_address_on_stream,
+ msg_field_classifier_copy_ipv4_destination_address_on_stream,
+ msg_field_classifier_copy_ipv6_traffic_class_on_stream,
+ msg_field_classifier_copy_ipv6_flow_label_on_stream,
+ msg_field_classifier_copy_ipv6_source_address_on_stream,
+ msg_field_classifier_copy_ipv6_destination_address_on_stream,
+ msg_field_classifier_copy_tcp_source_port_on_stream,
+ msg_field_classifier_copy_tcp_destination_port_on_stream,
+ msg_field_classifier_copy_udp_source_port_on_stream,
+ msg_field_classifier_copy_udp_destination_port_on_stream
+};
+typedef struct
+{
+ u32 len;
+ u32 ptr_shift;
+} info_rule_t;
+
+/////////////////////////////////////////////////////////////////////
+//////////////////// Classifier TOOLBOX ////////////////////////////
+/////////////////////////////////////////////////////////////////////
+
+
+
+len_t
+msg_field_classifier_copy_rule_ethernet_destination_address_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ ethernet_destination_address_t* address = &(data->ethernet_destination_address);
+
+ bcopy((void *)address, stream, 6);
+
+ return 6;
+}
+
+len_t
+msg_field_classifier_copy_rule_ethernet_destination_address_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ ethernet_destination_address_t* address = &(data->ethernet_destination_address);
+
+ bcopy(stream, (void *)address, 6);
+
+ return 6;
+}
+
+
+
+len_t
+msg_field_classifier_copy_rule_ethernet_source_address_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ ethernet_source_address_t* address = &(data->ethernet_source_address);
+
+ bcopy((void *)address, stream, 6);
+
+ return 6;
+}
+
+len_t
+msg_field_classifier_copy_rule_ethernet_source_address_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ ethernet_source_address_t* address = &(data->ethernet_source_address);
+
+ bcopy(stream, (void *)address, 6);
+
+ return 6;
+}
+
+
+
+
+len_t
+msg_field_classifier_copy_rule_vlan_user_priority_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ *stream = data->vlan_user_priority;
+
+ return 1;
+}
+
+len_t
+msg_field_classifier_copy_rule_vlan_user_priority_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ data->vlan_user_priority = *stream;
+
+ return 1;
+}
+
+
+
+
+len_t
+msg_field_classifier_copy_rule_vlan_id_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ *(u16*)stream = htons(data->vlan_id);
+
+ return 2;
+}
+
+len_t
+msg_field_classifier_copy_rule_vlan_id_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ data->vlan_id = ntohs(*(u16*)stream);
+
+ return 2;
+}
+
+
+
+len_t
+msg_field_classifier_copy_ipv4_type_of_service_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ *stream = data->ipv4_type_of_service;
+
+ return 1;
+}
+
+len_t
+msg_field_classifier_copy_ipv4_type_of_service_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ data->ipv4_type_of_service = *stream;
+
+ return 1;
+}
+
+
+
+len_t
+msg_field_classifier_copy_ipv4_protocol_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ *stream = data->ipv4_protocol;
+
+ return 1;
+}
+
+len_t
+msg_field_classifier_copy_ipv4_protocol_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ data->ipv4_protocol = *stream;
+
+ return 1;
+}
+
+
+
+len_t
+msg_field_classifier_copy_ipv4_source_address_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ ipv4_source_address_t* address = &(data->ipv4_source_address);
+
+ bcopy( (void *)address, (void *)stream, 4);
+
+ return 4;
+}
+
+len_t
+msg_field_classifier_copy_ipv4_source_address_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ ipv4_source_address_t* dest = &(data->ipv4_source_address);
+
+ bcopy( stream, (void *)dest, 4);
+
+ return 4;
+}
+
+
+
+len_t
+msg_field_classifier_copy_ipv4_destination_address_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ ipv4_destination_address_t* address = &(data->ipv4_destination_address);
+
+ bcopy( (void*)address, stream, 4);
+
+ return 4;
+}
+
+len_t
+msg_field_classifier_copy_ipv4_destination_address_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ ipv4_destination_address_t* dest = &(data->ipv4_destination_address);
+
+ bcopy( stream, (void*)dest, 4);
+
+ return 4;
+}
+
+
+
+
+len_t
+msg_field_classifier_copy_ipv6_traffic_class_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ *stream = data->ipv6_traffic_class;
+
+ return 1;
+}
+
+len_t
+msg_field_classifier_copy_ipv6_traffic_class_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ data->ipv6_traffic_class = *stream;
+
+ return 1;
+}
+
+
+
+len_t
+msg_field_classifier_copy_ipv6_flow_label_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ ipv6_flow_label_t* flow = &(data->ipv6_flow_label);
+
+ bcopy( (void*)flow, stream, 3);
+
+ return 3;
+}
+
+len_t
+msg_field_classifier_copy_ipv6_flow_label_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ ipv6_flow_label_t* flow = &(data->ipv6_flow_label);
+
+ bcopy( stream, (void*)flow, 3);
+
+ return 3;
+}
+
+
+
+len_t
+msg_field_classifier_copy_ipv6_source_address_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ ipv6_source_address_t* address = &(data->ipv6_source_address);
+
+ bcopy( (void*)address, stream, 16);
+
+ return 16;
+}
+
+len_t
+msg_field_classifier_copy_ipv6_source_address_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ ipv6_source_address_t* address = &(data->ipv6_source_address);
+
+ bcopy( stream, (void*)address, 16);
+
+ return 16;
+}
+
+
+
+
+len_t
+msg_field_classifier_copy_ipv6_destination_address_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ ipv6_destination_address_t* address = &(data->ipv6_destination_address);
+
+ bcopy( (void*)address, stream, 16);
+
+ return 16;
+}
+
+len_t
+msg_field_classifier_copy_ipv6_destination_address_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ ipv6_destination_address_t* address = &(data->ipv6_destination_address);
+
+ bcopy( stream, (void*)address, 16);
+
+ return 16;
+}
+
+
+
+len_t
+msg_field_classifier_copy_tcp_source_port_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ *(u16*)stream = htons(data->tcp_source_port);
+
+ return 2;
+}
+
+len_t
+msg_field_classifier_copy_tcp_source_port_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ data->tcp_source_port = ntohs(*(u16*)stream );
+
+ return 2;
+}
+
+
+
+len_t
+msg_field_classifier_copy_tcp_destination_port_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ *(u16*)stream = htons(data->tcp_destination_port);
+
+ return 2;
+}
+
+len_t
+msg_field_classifier_copy_tcp_destination_port_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ data->tcp_destination_port = ntohs(*(u16*)stream);
+
+ return 2;
+}
+
+
+
+len_t
+msg_field_classifier_copy_udp_source_port_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ *(u16*)stream = htons(data->udp_source_port);
+
+ return 2;
+}
+
+len_t
+msg_field_classifier_copy_udp_source_port_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ data->udp_source_port = ntohs(*(u16*)stream);
+
+ return 2;
+}
+
+
+
+len_t
+msg_field_classifier_copy_udp_destination_port_on_stream(u8* stream, classifier_rules_data_t* data)
+{
+ *(u16*)stream = htons(data->udp_destination_port);
+
+ return 2;
+}
+
+len_t
+msg_field_classifier_copy_udp_destination_port_from_stream(u8* stream, classifier_rules_data_t* data)
+{
+ data->udp_destination_port = ntohs(*(u16*)stream);
+
+ return 2;
+}
+
+////////////////////////////////////////////////////////////////////
+////////////////// Main Classifier Function ////////////////////////
+////////////////////////////////////////////////////////////////////
+
+
+/**
+ * Init a Classifier_rules structures
+ * \param classifier_rules pointer of the data to be initialized
+ *
+ */
+void
+msg_field_classifier_init(classifier_rules_t* classifier_rules)
+{
+ bzero(classifier_rules, sizeof(classifier_rules_t));
+
+}
+
+
+
+/**
+ * Get Classifier from stream
+ * \param stream the source stream
+ * \param classifier_rules destination of the data
+ * \return len the function return the length of the classifier_rules frame on the stream,
+ * this value does not correspond with the reality when the frame contains vendor field
+ *
+ */
+len_t
+msg_field_classifier_get_from_stream (u8* stream, classifier_rules_t* classifier_rules)
+{
+ int nbr_classifier_rules;
+ int rule_index = 0;
+ u8* local_stream;
+ len_t len = 0;
+
+ dbg_assert_ptr (stream);
+ dbg_assert_ptr (classifier_rules);
+
+ // Init
+ classifier_rules->classifier_version = *stream; stream++;
+ nbr_classifier_rules = *stream;stream++;
+
+ local_stream = stream;
+
+ while (rule_index < nbr_classifier_rules)
+ {
+ // get the Classifier Rule Identifier
+ u8 classifier_rule_id = *local_stream;
+ len++;local_stream++;
+
+ dbg_assert_print( (classifier_rule_id < 0x10) || (classifier_rule_id > 0xDF), "Classifier Rule Identifier not valid - received fid: 0x%x", classifier_rule_id);
+
+ classifier_rules->data.classifier_rules_available_block |= (0x01 << classifier_rule_id);
+
+ if (classifier_rule_id > 0xDF)
+ {
+ // Vendor defined Classifier Rule
+ nbr_classifier_rules = rule_index;
+ break;
+ }
+ else
+ {
+ // Homeplug AV Classifier Rule
+ len += copy_classifier_from_stream_tb[classifier_rule_id](local_stream, &(classifier_rules->data));
+ }
+
+
+ local_stream = stream + len;
+ rule_index ++;
+ }
+
+ classifier_rules->nbr_rules = nbr_classifier_rules;
+
+ cp_dbg_classifier_rule(*classifier_rules);
+
+ return len + 2;
+}
+
+
+
+
+/**
+ * set Classifier Rules on stream
+ * \param stream Destination.
+ * \param classifier_rules Source.
+ * \return Length of the data.
+ */
+len_t
+msg_field_classifier_set_on_stream(u8* stream, classifier_rules_t* classifier_rules)
+{
+ u8 index_rules;
+ u8* local_stream;
+ u32 available_rules = classifier_rules->data.classifier_rules_available_block;
+ len_t len = 0;
+
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(classifier_rules);
+ cp_dbg_classifier_rule(*classifier_rules);
+
+ bcopy( classifier_rules, stream, 2);//Copy of Classifier version and nbr of rules
+
+ stream += 2;
+
+ local_stream = stream;
+ // copy of the rules
+ for(index_rules = 0; index_rules < NBR_CLASSIFIER_FIELD; index_rules++)
+ {
+ u32 shift = available_rules >> index_rules;
+ u32 filtered = shift & FILTER_FIRST_BIT;
+
+ if ( filtered == 0X1)
+ {
+
+ *local_stream = index_rules;
+
+ local_stream++;
+ len ++;
+
+ len += copy_classifier_on_stream_tb[index_rules](local_stream, &(classifier_rules->data));
+ local_stream = stream + len;
+ }
+ }
+
+ return len+2;
+
+}
+
+
+
diff --git a/cesar/cp/msg/src/field/msg_field_cspec.c b/cesar/cp/msg/src/field/msg_field_cspec.c
new file mode 100644
index 0000000000..e148597300
--- /dev/null
+++ b/cesar/cp/msg/src/field/msg_field_cspec.c
@@ -0,0 +1,114 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}}
+ * \file msg_field_cspec.c
+ * \brief This file provides management functions for CSPEC (Connection Specification) field.
+ * \ingroup cp/msg
+ *
+ */
+
+#include "common/std.h"
+#include "lib/swap.h"
+#include "cp/msg/inc/msg_cm_conn.h"
+
+
+/**
+ * Initialize the CSPEC (Connection Specification) structure.
+ * \param cspec Pointer of the data to be initialized.
+ *
+ */
+void
+msg_field_cspec_init(cspec_t* cspec)
+{
+ cspec->len = 0;
+ msg_field_cinfo_init( &(cspec->cinfo_forward) );
+ msg_field_cinfo_init( &(cspec->cinfo_reverse) );
+ msg_field_qmp_init( &(cspec->qmp_forward) );
+ cspec->qmp_forward.forward_or_reverse = QMP_FORWARD;
+ msg_field_qmp_init( &(cspec->qmp_reverse) );
+ cspec->qmp_reverse.forward_or_reverse = QMP_REVERSE;
+}
+
+
+/**
+ * Get CSPEC field from a stream.
+ * \param stream Source Stream.
+ * \param cspec Destination.
+ * \return Length of the CSPEC data.
+ *
+ */
+len_t
+msg_field_cspec_get_from_stream(u8* stream, cspec_t* cspec)
+{
+ u8* local_stream = stream;
+ u8* stream_end;
+
+ dbg_assert_ptr( stream );
+ dbg_assert_ptr( cspec );
+
+ cspec->len = ntohs (*(u16*)local_stream); local_stream += 2;
+ stream_end = stream + cspec->len;
+
+ local_stream += msg_field_cinfo_get_from_stream(local_stream, &(cspec->cinfo_forward) );
+ local_stream += msg_field_cinfo_get_from_stream(local_stream, &(cspec->cinfo_reverse) );
+
+ if(cspec->cinfo_forward.valid == CINFO_VALID)
+ local_stream += msg_field_qmp_get_from_stream(local_stream, stream_end, &(cspec->qmp_forward), QMP_FORWARD);
+
+ if(cspec->cinfo_reverse.valid == CINFO_VALID)
+ msg_field_qmp_get_from_stream(local_stream, stream_end, &(cspec->qmp_reverse), QMP_REVERSE);
+
+ cp_dbg_cspec(*cspec);
+
+ return cspec->len;
+
+}
+
+
+
+
+/**
+ * Set CSPEC on stream.
+ * \param stream Data destination.
+ * \param cspec Data source.
+ * \return Length of the data copied.
+ *
+ */
+len_t
+msg_field_cspec_set_on_stream(u8 * stream, cspec_t* cspec)
+{
+ u8 * local_stream = stream;
+
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(cspec);
+ cp_dbg_cspec(*cspec);
+
+ //cspec_len
+ local_stream += 2;
+
+ // copy cinfo_forward
+ local_stream += msg_field_cinfo_set_on_stream( local_stream, &(cspec->cinfo_forward));
+
+ // copy cinfo_reverse
+ local_stream += msg_field_cinfo_set_on_stream( local_stream, &(cspec->cinfo_reverse));
+
+ // copy qmp_forward
+ if (cspec->cinfo_forward.valid == CINFO_VALID)
+ {
+ local_stream += msg_field_qmp_set_on_stream( local_stream, &(cspec->qmp_forward));
+ }
+
+ // copy qmp_reverse
+ if (cspec->cinfo_reverse.valid == CINFO_VALID)
+ {
+ local_stream += msg_field_qmp_set_on_stream( local_stream, &(cspec->qmp_reverse));
+ }
+
+ // copy cspec_len
+ *(u16*)stream = htons(local_stream-stream);
+ return local_stream - stream;
+}
diff --git a/cesar/cp/msg/src/field/msg_field_qmp.c b/cesar/cp/msg/src/field/msg_field_qmp.c
new file mode 100644
index 0000000000..b0351e38a3
--- /dev/null
+++ b/cesar/cp/msg/src/field/msg_field_qmp.c
@@ -0,0 +1,1189 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}}
+ * \file msg_field_qmp.c
+ * \brief This file provides management functions for QMP (QoS and Mac Parameters) field.
+ * \ingroup cp/msg
+ *
+ */
+
+#include "common/std.h"
+#include "lib/swap.h"
+#include "cp/msg/inc/msg_cm_conn.h"
+
+
+
+// Private definition
+typedef struct
+{
+ qmp_forward_or_reverse_t forward_or_reverse:8;
+ u8 qmp_len;
+ u8 fid;
+ u8 data[];
+} data_qmp_t;
+
+typedef void (*qmp_copy_from_stream_t)(u8*, qmp_t*);
+typedef len_t (*qmp_copy_from_qmp_t )(qmp_t*, u8*);
+
+void msg_field_qmp_copy_delay_bound_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_jitter_bound_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_average_msdu_size_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_maximum_msdu_size_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_average_data_rate_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_minimum_data_rate_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_maximum_data_rate_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_maximum_inter_txop_time_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_minimum_inter_txop_time_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_maximum_burst_size_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_exception_policy_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_inactivity_interval_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_msdu_error_rate_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_clst_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_cdesc_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_ats_tolerance_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_smallest_tolerable_data_rate_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_original_average_data_rate_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_rx_window_size_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_smoothing_buffer_size_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_bidirectional_burst_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_txops_per_beacon_period_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_average_number_of_pbs_per_txop_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_minimum_number_of_pbs_per_txop_from_stream_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_maximum_number_of_pbs_per_txop_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_ppb_threshold_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_surplus_bandwith_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_smallest_tolerable_average_number_of_pbs_per_txop_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_original_average_number_of_pbs_per_txop_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_cco_bidirectional_burst_from_stream(u8 * stream, qmp_t* qmp);
+void msg_field_qmp_copy_unknown_from_stream(u8 * stream, qmp_t* qmp);
+
+len_t msg_field_qmp_copy_delay_bound_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_jitter_bound_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_average_msdu_size_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_maximum_msdu_size_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_average_data_rate_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_minimum_data_rate_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_maximum_data_rate_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_maximum_inter_txop_time_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_minimum_inter_txop_time_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_maximum_burst_size_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_exception_policy_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_inactivity_interval_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_msdu_error_rate_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_clst_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_cdesc_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_ats_tolerance_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_smallest_tolerable_data_rate_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_original_average_data_rate_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_rx_window_size_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_smoothing_buffer_size_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_bidirectional_burst_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_txops_per_beacon_period_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_average_number_of_pbs_per_txop_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_minimum_number_of_pbs_per_txop_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_maximum_number_of_pbs_per_txop_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_ppb_threshold_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_surplus_bandwith_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_smallest_tolerable_average_number_of_pbs_per_txop_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_original_average_number_of_pbs_per_txop_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_cco_bidirectional_burst_from_qmp(qmp_t* qmp, u8* stream);
+len_t msg_field_qmp_copy_unknown_from_qmp(qmp_t* qmp, u8* stream);
+
+
+
+
+qmp_copy_from_stream_t qmp_copy_from_stream[32] =
+{
+ msg_field_qmp_copy_delay_bound_from_stream,
+ msg_field_qmp_copy_jitter_bound_from_stream,
+ msg_field_qmp_copy_average_msdu_size_from_stream,
+ msg_field_qmp_copy_maximum_msdu_size_from_stream,
+ msg_field_qmp_copy_average_data_rate_from_stream,
+ msg_field_qmp_copy_minimum_data_rate_from_stream,
+ msg_field_qmp_copy_maximum_data_rate_from_stream,
+ msg_field_qmp_copy_maximum_inter_txop_time_from_stream,
+ msg_field_qmp_copy_minimum_inter_txop_time_from_stream,
+ msg_field_qmp_copy_maximum_burst_size_from_stream,
+ msg_field_qmp_copy_exception_policy_from_stream,
+ msg_field_qmp_copy_inactivity_interval_from_stream,
+ msg_field_qmp_copy_msdu_error_rate_from_stream,
+ msg_field_qmp_copy_clst_from_stream,
+ msg_field_qmp_copy_cdesc_from_stream,
+ msg_field_qmp_copy_unknown_from_stream,
+ msg_field_qmp_copy_ats_tolerance_from_stream,
+ msg_field_qmp_copy_smallest_tolerable_data_rate_from_stream,
+ msg_field_qmp_copy_original_average_data_rate_from_stream,
+ msg_field_qmp_copy_rx_window_size_from_stream,
+ msg_field_qmp_copy_smoothing_buffer_size_from_stream,
+ msg_field_qmp_copy_bidirectional_burst_from_stream,
+ msg_field_qmp_copy_txops_per_beacon_period_from_stream,
+ msg_field_qmp_copy_average_number_of_pbs_per_txop_from_stream,
+ msg_field_qmp_copy_minimum_number_of_pbs_per_txop_from_stream_from_stream,
+ msg_field_qmp_copy_maximum_number_of_pbs_per_txop_from_stream,
+ msg_field_qmp_copy_ppb_threshold_from_stream,
+ msg_field_qmp_copy_surplus_bandwith_from_stream,
+ msg_field_qmp_copy_unknown_from_stream,
+ msg_field_qmp_copy_smallest_tolerable_average_number_of_pbs_per_txop_from_stream,
+ msg_field_qmp_copy_original_average_number_of_pbs_per_txop_from_stream,
+ msg_field_qmp_copy_cco_bidirectional_burst_from_stream
+
+};
+
+
+qmp_copy_from_qmp_t qmp_copy_from_qmp[32]=
+{
+ msg_field_qmp_copy_delay_bound_from_qmp,
+ msg_field_qmp_copy_jitter_bound_from_qmp,
+ msg_field_qmp_copy_average_msdu_size_from_qmp,
+ msg_field_qmp_copy_maximum_msdu_size_from_qmp,
+ msg_field_qmp_copy_average_data_rate_from_qmp,
+ msg_field_qmp_copy_minimum_data_rate_from_qmp,
+ msg_field_qmp_copy_maximum_data_rate_from_qmp,
+ msg_field_qmp_copy_maximum_inter_txop_time_from_qmp,
+ msg_field_qmp_copy_minimum_inter_txop_time_from_qmp,
+ msg_field_qmp_copy_maximum_burst_size_from_qmp,
+ msg_field_qmp_copy_exception_policy_from_qmp,
+ msg_field_qmp_copy_inactivity_interval_from_qmp,
+ msg_field_qmp_copy_msdu_error_rate_from_qmp,
+ msg_field_qmp_copy_clst_from_qmp,
+ msg_field_qmp_copy_cdesc_from_qmp,
+ msg_field_qmp_copy_unknown_from_qmp, // vendor specific
+ msg_field_qmp_copy_ats_tolerance_from_qmp,
+ msg_field_qmp_copy_smallest_tolerable_data_rate_from_qmp,
+ msg_field_qmp_copy_original_average_data_rate_from_qmp,
+ msg_field_qmp_copy_rx_window_size_from_qmp,
+ msg_field_qmp_copy_smoothing_buffer_size_from_qmp,
+ msg_field_qmp_copy_bidirectional_burst_from_qmp,
+ msg_field_qmp_copy_txops_per_beacon_period_from_qmp,
+ msg_field_qmp_copy_average_number_of_pbs_per_txop_from_qmp,
+ msg_field_qmp_copy_minimum_number_of_pbs_per_txop_from_qmp,
+ msg_field_qmp_copy_maximum_number_of_pbs_per_txop_from_qmp,
+ msg_field_qmp_copy_ppb_threshold_from_qmp,
+ msg_field_qmp_copy_surplus_bandwith_from_qmp,
+ msg_field_qmp_copy_unknown_from_qmp,
+ msg_field_qmp_copy_smallest_tolerable_average_number_of_pbs_per_txop_from_qmp,
+ msg_field_qmp_copy_original_average_number_of_pbs_per_txop_from_qmp,
+ msg_field_qmp_copy_cco_bidirectional_burst_from_qmp
+
+
+};
+////////////////////////////////////////////////////////////////////
+//////////////////////////// QMP TOOLBOX////////////////////////////
+////////////////////////////////////////////////////////////////////
+
+
+void
+msg_field_qmp_copy_delay_bound_from_stream(u8* stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+
+ qmp->valid.delay_bound_available = true;
+
+ qmp->cm.delay_bound = ntohl( *(u32*)stream);
+
+}
+
+len_t
+msg_field_qmp_copy_delay_bound_from_qmp(qmp_t* qmp, u8* stream)
+{
+
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.delay_bound_available, "PRE : no delay_bound_present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x04; stream++; // body length
+ *stream = 0x00; stream++; // FID : delay bound
+ *(u32*)stream = htonl(qmp->cm.delay_bound);
+
+ return 7;
+
+}
+
+
+
+void
+msg_field_qmp_copy_jitter_bound_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert(stream);
+ dbg_assert(qmp);
+
+ qmp->valid.jitter_bound_available = true;
+
+ qmp->cm.jitter_bound = ntohl( *(u32*)stream);
+}
+
+len_t
+msg_field_qmp_copy_jitter_bound_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.jitter_bound_available, "PRE : no jitter_bound_present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x04; stream++; // body length
+ *stream = 0x01; stream++; // FID : delay bound
+ *(u32*)stream = htonl(qmp->cm.jitter_bound);
+
+ return 7;
+}
+
+
+
+void
+msg_field_qmp_copy_average_msdu_size_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+
+ qmp->valid.average_msdu_size_available = true;
+
+ qmp->cm.average_msdu_size = ntohs( *(u16*)stream);
+
+}
+
+len_t
+msg_field_qmp_copy_average_msdu_size_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.average_msdu_size_available, "PRE : no average_msdu_size_present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x02; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cm.average_msdu_size);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_maximum_msdu_size_from_stream(u8 * stream, qmp_t* qmp)
+{
+ qmp->valid.maximum_msdu_size_available = true;
+
+ qmp->cm.maximum_msdu_size = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_maximum_msdu_size_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.maximum_msdu_size_available, "PRE : no maximum_msdu_size_present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x03; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cm.maximum_msdu_size);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_average_data_rate_from_stream(u8 * stream, qmp_t* qmp)
+{
+ qmp->valid.average_data_rate_available = true;
+
+ qmp->cm.average_data_rate = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_average_data_rate_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.average_data_rate_available, "PRE : no average_data_rate_present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x04; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cm.average_data_rate);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_minimum_data_rate_from_stream(u8 * stream, qmp_t* qmp)
+{
+ qmp->valid.minimum_data_rate_available = true;
+
+ qmp->cm.minimum_data_rate = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_minimum_data_rate_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.minimum_data_rate_available, "PRE : no minimum_data_rate_present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x05; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cm.minimum_data_rate);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_maximum_data_rate_from_stream(u8 * stream, qmp_t* qmp)
+{
+ qmp->valid.maximum_data_rate_available = true;
+
+ qmp->cm.maximum_data_rate = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_maximum_data_rate_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.maximum_data_rate_available, "PRE : no maximum_data_rate present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x06; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cm.maximum_data_rate);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_maximum_inter_txop_time_from_stream(u8 * stream, qmp_t* qmp)
+{
+ qmp->valid.maximum_inter_txop_time_available = true;
+
+ qmp->cm.maximum_inter_txop_time = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_maximum_inter_txop_time_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.maximum_inter_txop_time_available, "PRE : no maximum_inter_txop_time present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x07; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cm.maximum_inter_txop_time);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_minimum_inter_txop_time_from_stream(u8 * stream, qmp_t* qmp)
+{
+ qmp->valid.minimum_inter_txop_time_available = true;
+
+ qmp->cm.minimum_inter_txop_time = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_minimum_inter_txop_time_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.minimum_inter_txop_time_available, "PRE : no minimum_inter_txop_time present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x08; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cm.minimum_inter_txop_time);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_maximum_burst_size_from_stream(u8 * stream, qmp_t* qmp)
+{
+ qmp->valid.maximum_burst_size_available = true;
+
+ qmp->cm.maximum_burst_size = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_maximum_burst_size_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.maximum_burst_size_available, "PRE : no maximum_burst_size present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x09; stream++; // FID : maximum burst size
+ *(u16*)stream = htons(qmp->cm.maximum_burst_size);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_exception_policy_from_stream(u8 * stream, qmp_t* qmp)
+{
+ qmp->valid.exception_policy_available = true;
+
+ qmp->cm.exception_policy = *stream;
+}
+
+len_t
+msg_field_qmp_copy_exception_policy_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.exception_policy_available, "PRE : no exception_policy present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x01; stream++; // body length
+ *stream = 0x0A; stream++; // FID : delay bound
+ *stream = qmp->cm.exception_policy;
+
+ return 4;
+}
+
+
+
+void
+msg_field_qmp_copy_inactivity_interval_from_stream(u8 * stream, qmp_t* qmp)
+{
+ qmp->valid.inactivity_interval_available = true;
+
+ qmp->cm.inactivity_interval = ntohl( *(u32*)stream);
+}
+
+len_t
+msg_field_qmp_copy_inactivity_interval_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.inactivity_interval_available, "PRE : no inactivity_interval on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x04; stream++; // body length
+ *stream = 0x0B; stream++; // FID : delay bound
+ *(u32*)stream = htonl(qmp->cm.inactivity_interval);
+
+ return 7;
+}
+
+
+
+void
+msg_field_qmp_copy_msdu_error_rate_from_stream(u8 * stream, qmp_t* qmp)
+{
+ qmp->valid.msdu_error_rate_available = true;
+
+ qmp->cm.msdu_error_rate = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_msdu_error_rate_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.msdu_error_rate_available, "PRE : no msdu_error_rate present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x0C; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cm.msdu_error_rate);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_clst_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+
+ qmp->valid.clst_available = true;
+
+ qmp->cm.clst = *stream;
+}
+
+len_t
+msg_field_qmp_copy_clst_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.clst_available, "PRE : no clst present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x01; stream++; // body length
+ *stream = 0x0D; stream++; // FID : delay bound
+ *stream = qmp->cm.clst;
+
+ return 4;
+}
+
+
+
+void
+msg_field_qmp_copy_cdesc_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+
+ qmp->valid.cdesc_available = true;
+
+ qmp->cm.cdesc.ip_version = *stream;
+ stream ++;
+
+ if( qmp->cm.cdesc.ip_version == IP_VERSION_4)
+ {
+ bcopy(stream, &qmp->cm.cdesc.ipv4_source_address , 4); stream += 4; // copy source ip address
+ qmp->cm.cdesc.source_port = ntohs( *(u16*)stream);stream += 2;
+
+ bcopy(stream, &qmp->cm.cdesc.ipv4_destination_address , 4); stream += 4; // copy destination ip address
+ qmp->cm.cdesc.destination_port = ntohs( *(u16*)stream); stream += 2;
+
+ }
+ else if ( qmp->cm.cdesc.ip_version == IP_VERSION_6)
+ {
+ bcopy(stream, &qmp->cm.cdesc.ipv6_source_address, 36);
+ qmp->cm.cdesc.destination_port = ntohs(qmp->cm.cdesc.destination_port);
+ qmp->cm.cdesc.source_port = ntohs(qmp->cm.cdesc.source_port);
+ }
+ else
+ {
+ dbg_assert_print(true, "!!! ERROR : ip version invalid");
+ }
+ qmp->cm.cdesc.protocol_type = *stream;
+
+}
+
+len_t
+msg_field_qmp_copy_cdesc_from_qmp(qmp_t* qmp, u8* stream)
+{
+ len_t len = 0;
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.cdesc_available, "PRE : no cdesc present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+
+ if(qmp->cm.cdesc.ip_version == IP_VERSION_4)
+ {
+ *stream = 0x0E; stream++; // body length
+ *stream = 0x0E; stream++; // FID : delay bound
+ *stream = qmp->cm.cdesc.ip_version; stream++;
+
+ bcopy(qmp->cm.cdesc.ipv4_source_address,stream, sizeof( qmp->cm.cdesc.ipv4_source_address ) );
+ stream += sizeof( qmp->cm.cdesc.ipv4_source_address );
+
+ *(u16*)stream = htons(qmp->cm.cdesc.source_port);
+ stream += 2;
+
+ bcopy(qmp->cm.cdesc.ipv4_destination_address,stream, sizeof( qmp->cm.cdesc.ipv4_destination_address ) );
+ stream += sizeof( qmp->cm.cdesc.ipv4_destination_address);
+
+ *(u16*)stream = htons(qmp->cm.cdesc.destination_port);
+ stream += 2;
+
+ len = 17;
+ }
+ else if(qmp->cm.cdesc.ip_version == IP_VERSION_6)
+ {
+ *stream = 0x26; stream++; // body length
+ *stream = 0x0E; stream++; // FID : delay bound
+ *stream = qmp->cm.cdesc.ip_version; stream++;
+
+ bcopy(qmp->cm.cdesc.ipv4_source_address,stream, 16 ); stream += 16;
+ *(u16*)stream = htons(qmp->cm.cdesc.source_port); stream += 2;
+ bcopy(qmp->cm.cdesc.ipv4_destination_address,stream, 16 ); stream += 16;
+ *(u16*)stream = htons(qmp->cm.cdesc.destination_port); stream += 2;
+
+ len = 41;
+ }
+ else
+ dbg_assert_print(true,"Invalid ip version");
+
+ *stream = qmp->cm.cdesc.protocol_type;
+
+
+ return len;
+}
+
+
+
+void
+msg_field_qmp_copy_ats_tolerance_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+
+ qmp->valid.ats_tolerance_available = true;
+
+ qmp->cm.ats_tolerance = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_ats_tolerance_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.ats_tolerance_available, "PRE : no ats_tolerance present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x10; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cm.ats_tolerance);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_smallest_tolerable_data_rate_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+
+ qmp->valid.smallest_tolerable_data_rate_available = true;
+
+ qmp->cm.smallest_tolerable_data_rate = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_smallest_tolerable_data_rate_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.smallest_tolerable_data_rate_available, "PRE : no smallest_tolerable_data_rate present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x11; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cm.smallest_tolerable_data_rate);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_original_average_data_rate_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+
+ qmp->valid.original_average_data_rate_available = true;
+
+ qmp->cm.original_average_data_rate = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_original_average_data_rate_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.original_average_data_rate_available, "PRE : no original_average_data_rate present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x12; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cm.original_average_data_rate);
+
+ return 5;
+}
+
+
+
+
+void
+msg_field_qmp_copy_rx_window_size_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+
+ qmp->valid.rx_window_size_available = true;
+
+ qmp->cm.rx_window_size = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_rx_window_size_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.rx_window_size_available, "PRE : no rx_window_size present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x13; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cm.rx_window_size);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_smoothing_buffer_size_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+
+ qmp->valid.smoothing_buffer_size_available = true;
+
+ bcopy(stream, &qmp->cm.smoothing_buffer_size, 3);
+
+#if DEFS_BIG_ENDIAN
+
+#else
+#define var (qmp->cm.smoothing_buffer_size)
+ var = (var & 0x0000FF) << 16 | (var & 0x00FF00) | (var & 0xFF0000) >> 16;
+#endif
+}
+
+len_t
+msg_field_qmp_copy_smoothing_buffer_size_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.smoothing_buffer_size_available, "PRE : no smoothing_buffer_sizepresent on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x03; stream++; // body length
+ *stream = 0x14; stream++; // FID : delay bound
+
+
+#if DEFS_BIG_ENDIAN
+
+#else
+#define var (qmp->cm.smoothing_buffer_size)
+ *(u32*)stream = (var & 0x0000FF) << 16 | (var & 0x00FF00) | (var & 0xFF0000) >> 16;
+#endif
+
+
+ return 6;
+}
+
+
+
+void
+msg_field_qmp_copy_bidirectional_burst_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert(stream);
+ dbg_assert(qmp);
+
+ qmp->valid.bidirectional_burst_available = true;
+
+ qmp->cm.bidirectional_burst = *stream;
+}
+
+len_t
+msg_field_qmp_copy_bidirectional_burst_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.bidirectional_burst_available, "PRE : no bidirectional_burst present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x01; stream++; // body length
+ *stream = 0x15; stream++; // FID : delay bound
+ *stream = qmp->cm.bidirectional_burst;
+
+ return 4;
+}
+
+
+
+void
+msg_field_qmp_copy_txops_per_beacon_period_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+ qmp->valid.txops_per_beacon_period_available = true;
+
+ qmp->cco.txops_per_beacon_period = *stream;
+}
+
+len_t
+msg_field_qmp_copy_txops_per_beacon_period_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.txops_per_beacon_period_available, "PRE : no txops_per_beacon_period present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x01; stream++; // body length
+ *stream = 0x80; stream++; // FID : delay bound
+ *stream = qmp->cco.txops_per_beacon_period;
+
+ return 4;
+}
+
+
+
+void
+msg_field_qmp_copy_average_number_of_pbs_per_txop_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert(stream);
+ dbg_assert(qmp);
+
+ qmp->valid.average_number_of_pbs_per_txop_available = true;
+
+ qmp->cco.average_number_of_pbs_per_txop = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_average_number_of_pbs_per_txop_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.average_number_of_pbs_per_txop_available, "PRE : no average_number_of_pbs_per_txop present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x81; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cco.average_number_of_pbs_per_txop);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_minimum_number_of_pbs_per_txop_from_stream_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+
+ qmp->valid.minimum_number_of_pbs_per_txop_available = true;
+
+ qmp->cco.minimum_number_of_pbs_per_txop = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_minimum_number_of_pbs_per_txop_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.minimum_number_of_pbs_per_txop_available, "PRE : no minimum_number_of_pbs_per_txop present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x82; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cco.minimum_number_of_pbs_per_txop);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_maximum_number_of_pbs_per_txop_from_stream(u8 * stream, qmp_t* qmp)
+{
+ qmp->valid.maximum_number_of_pbs_per_txop_available = true;
+
+ qmp->cco.maximum_number_of_pbs_per_txop = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_maximum_number_of_pbs_per_txop_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.maximum_number_of_pbs_per_txop_available, "PRE : no maximum_number_of_pbs_per_txop present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x83; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cco.maximum_number_of_pbs_per_txop);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_ppb_threshold_from_stream(u8 * stream, qmp_t* qmp)
+{
+ qmp->valid.ppb_threshold_available = true;
+
+ qmp->cco.ppb_threshold = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_ppb_threshold_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.ppb_threshold_available, "PRE : no ppb_threshold present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x84; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cco.ppb_threshold);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_surplus_bandwith_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+
+ qmp->valid.surplus_bandwith_available = true;
+
+ qmp->cco.surplus_bandwith = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_surplus_bandwith_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.ppb_threshold_available, "PRE : no ppb_threshold present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x85; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cco.ppb_threshold);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_smallest_tolerable_average_number_of_pbs_per_txop_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+
+ qmp->valid.smallest_tolerable_average_number_of_pbs_per_txop_available = true;
+
+ qmp->cco.smallest_tolerable_average_number_of_pbs_per_txop = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_smallest_tolerable_average_number_of_pbs_per_txop_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.smallest_tolerable_average_number_of_pbs_per_txop_available, "PRE : no smallest_tolerable_average_number_of_pbs_per_txop present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x87; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cco.smallest_tolerable_average_number_of_pbs_per_txop);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_original_average_number_of_pbs_per_txop_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+
+ qmp->valid.original_average_number_of_pbs_per_txop_available = true;
+
+ qmp->cco.original_average_number_of_pbs_per_txop = ntohs( *(u16*)stream);
+}
+
+len_t
+msg_field_qmp_copy_original_average_number_of_pbs_per_txop_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.original_average_number_of_pbs_per_txop_available, "PRE : no original_average_number_of_pbs_per_txop present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x02; stream++; // body length
+ *stream = 0x88; stream++; // FID : delay bound
+ *(u16*)stream = htons(qmp->cco.original_average_number_of_pbs_per_txop);
+
+ return 5;
+}
+
+
+
+void
+msg_field_qmp_copy_cco_bidirectional_burst_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+
+ qmp->valid.cco_bidirectional_burst_available = true;
+
+ qmp->cco.cco_bidirectional_burst = *stream;
+}
+
+len_t
+msg_field_qmp_copy_cco_bidirectional_burst_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_ptr(qmp);
+ dbg_assert_ptr(stream);
+ dbg_assert_print(qmp->valid.cco_bidirectional_burst_available, "PRE : no cco_bidirectional_burst present on qmp frame");
+
+ *stream = qmp->forward_or_reverse; stream ++;
+ *stream = 0x01; stream++; // body length
+ *stream = 0x89; stream++; // FID : delay bound
+ *stream = qmp->cco.cco_bidirectional_burst;
+
+ return 4;
+}
+
+
+
+void
+msg_field_qmp_copy_unknown_from_stream(u8 * stream, qmp_t* qmp)
+{
+ dbg_assert_print(true, "Error unknown fid on QMP");
+}
+
+
+len_t
+msg_field_qmp_copy_unknown_from_qmp(qmp_t* qmp, u8* stream)
+{
+ dbg_assert_print(true, "Erreur copy unknown");
+ return 0;
+}
+
+
+
+u8
+qmp_get_index_from_fid(u8 fid)
+{
+ dbg_assert_print(fid < 0x16 || fid >= 0x80, "PRE : fid value not valid");
+
+ if( fid < 0x16)
+ { // cm fid
+ return fid;
+ }
+ else
+ { // cco fid
+ dbg_assert_print( (fid < 0x8A) && ( fid > 0x7F), "POST: invalid fid range = %x", fid);
+ return fid-0x6A;
+ }
+
+}
+////////////////////////////////////////////////////////////////////
+//////////////////////// Main QMP Function /////////////////////////
+////////////////////////////////////////////////////////////////////
+
+
+
+/**
+ * Initialize the QMP structure.
+ *
+ * \param qmp Data to be initialized.
+ *
+ */
+void
+msg_field_qmp_init(qmp_t* qmp)
+{
+ bzero(qmp, sizeof(qmp_t));
+}
+
+
+
+/**
+ * Get a QMP field from a stream.
+ *
+ * \param stream Stream of data contening the qmp field.
+ * \param qmp Data destination.
+ * \param qmp_type Type of QMP frame to read (QMP_FORWARD or QMP_REVERSE defined on CSPEC).
+ * return Length of the data;
+ *
+ */
+len_t
+msg_field_qmp_get_from_stream (u8* stream, u8* stream_end, qmp_t * qmp, qmp_forward_or_reverse_t qmp_type)
+{
+ data_qmp_t* packet;
+ len_t len;
+
+ dbg_assert_ptr (stream);
+ dbg_assert (*stream == qmp_type); // is really a forward qmp stream
+ dbg_assert_ptr (qmp);
+
+ qmp->forward_or_reverse = qmp_type;
+
+ packet = (data_qmp_t*)(stream);
+
+ while ( (packet->forward_or_reverse == qmp_type) && ( (u8*)packet < stream_end))
+ {
+ u8 index;
+
+ dbg_assert_ptr(packet);
+
+ index = qmp_get_index_from_fid(packet->fid);
+
+ qmp_copy_from_stream[index]((u8*)(packet->data), qmp);
+
+ len = packet->qmp_len;
+ packet = (data_qmp_t *)((u8*)(packet)+(len) + 3);
+ }
+
+ cp_dbg_qmp(*qmp);
+ return (len_t)((u8*)packet-stream);
+}
+
+
+
+/**
+ * Set QMP field on stream.
+ *
+ * \param stream Data destination.
+ * \param qmp Data source.
+ * \return Length of the data.
+ */
+len_t
+msg_field_qmp_set_on_stream(u8 * stream, qmp_t* qmp)
+{
+ len_t len = 0;
+ int qmp_field_i;
+ u8 * local_stream = stream;
+
+ dbg_assert_ptr(stream);
+ dbg_assert_ptr(qmp);
+ cp_dbg_qmp(*qmp);
+
+ for(qmp_field_i = 0; qmp_field_i < 32; qmp_field_i++ )
+ {
+ if ( ( (0x01<< qmp_field_i) & qmp->valid_in_block ) != 0)
+ {
+ len += qmp_copy_from_qmp[qmp_field_i](qmp, local_stream);
+
+ local_stream = stream + len;
+ }
+
+ }
+
+ return len;
+}
+
+
diff --git a/cesar/cp/msg/src/msg.c b/cesar/cp/msg/src/msg.c
new file mode 100644
index 0000000000..b5eb37cdca
--- /dev/null
+++ b/cesar/cp/msg/src/msg.c
@@ -0,0 +1,336 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/msg/msg.c
+ * \brief MME message processing
+ * \ingroup cp_msg
+ */
+
+#include "common/std.h"
+
+#include "cp/beacon/inc/bentry.h"
+#include "cp/beacon/inc/beacons_ctx.h"
+#include "cp/beacon/forward.h"
+#include "cp/beacon/inc/beacons_work.h"
+
+#include "cp/msg/msg.h"
+
+/*
+ * this array describe messages, their prefered destination and the function
+ * which process it.
+ * the array must be ordered on the first field of each line.
+ */
+const msg_list_mme_t msg_list_m[] =
+ {
+ { CC_CCO_APPOINT_REQ, 0 },
+ { CC_CCO_APPOINT_CNF, 0 },
+ { CC_BACKUP_APPOINT_REQ, 0 },
+ { CC_BACKUP_APPOINT_CNF, 0 },
+ { CC_LINK_INFO_REQ, 0 },
+ { CC_LINK_INFO_CNF, 0 },
+ { CC_LINK_INFO_IND, 0 },
+ { CC_LINK_INFO_RSP, 0 },
+ { CC_HANDOVER_REQ, 0 },
+ { CC_HANDOVER_CNF, 0 },
+ { CC_HANDOVER_INFO_IND, 0 },
+ { CC_HANDOVER_INFO_RSP, 0 },
+ // TBC ...
+ {CC_ASSOC_REQ, RECEIVE_CC_ASSOC_REQ},
+ {CC_ASSOC_CNF, RECEIVE_CC_ASSOC_CNF},
+ {CC_SET_TEI_MAP_REQ, RECEIVE_CC_SET_TEI_MAP_REQ},
+ {CC_SET_TEI_MAP_IND, RECEIVE_CC_SET_TEI_MAP_IND},
+
+ { CM_UNASSOCIATED_STA_IND, RECEIVE_USTA_MME},
+ // TBC ...
+
+ {DRV_STA_SET_MAC_ADDR_REQ, RECEIVE_DRV_SET_MAC_ADDRESS},
+ {DRV_STA_SET_CCO_PREF_REQ, RECEIVE_DRV_SET_CCO_PREFERENCE_REQ},
+ {DRV_STA_SET_WAS_CCO_REQ, RECEIVE_DRV_SET_WAS_CCO},
+ {DRV_STA_SET_NPW_REQ, RECEIVE_DRV_SET_NPW_REQ},
+ {DRV_STA_SET_DPW_REQ, RECEIVE_DRV_SET_DPW_REQ},
+ {DRV_STA_SET_SL_REQ, RECEIVE_DRV_SET_SL},
+ {DRV_STA_SET_M_STA_HFID_REQ, RECEIVE_DRV_SET_M_STA_HFID},
+ {DRV_STA_SET_U_STA_HFID_REQ, RECEIVE_DRV_SET_U_STA_HFID},
+ {DRV_STA_SET_AVLN_HFID_REQ, RECEIVE_DRV_SET_AVLN_HFID},
+ {DRV_STA_SET_TONEMASK_REQ, RECEIVE_DRV_SET_TONEMASK},
+ {DRV_STA_START_REQ, RECEIVE_DRV_MAC_START_REQ},
+ {DRV_STA_STOP_REQ, RECEIVE_DRV_MAC_STOP_IND}
+ /*
+ {DRV_STA_SET_NID_REQ, RECEIVE_DRV_SET_NID},
+ {DRV_STA_SET_SNID_REQ, RECEIVE_DRV_SET_SNID},
+ */
+ };
+
+const char *cst_str_drv_mme_req[] = {
+ "DRV_STA_SET_MAC_ADDR.REQ",
+ "DRV_STA_SET_CCO_PREF.REQ",
+ "DRV_STA_SET_WAS_CCO.REQ",
+ "DRV_STA_SET_NPW.REQ",
+ "DRV_STA_SET_DPW.REQ",
+ "DRV_STA_SET_SL.REQ",
+ "DRV_STA_SET_M_STA_HFID.REQ",
+ "DRV_STA_SET_U_STA_HFID.REQ",
+ "DRV_STA_SET_AVLN_HFID.REQ",
+ "DRV_STA_SET_TONEMASK.REQ",
+ "DRV_STA_START.REQ",
+ "DRV_STA_STOP.REQ"
+};
+
+const char *cst_str_drv_mme_cnf[] = {
+ "DRV_STA_SET_MAC_ADDR.CNF",
+ "DRV_STA_SET_CCO_PREF.CNF",
+ "DRV_STA_SET_WAS_CCO.CNF",
+ "DRV_STA_SET_NPW.CNF",
+ "DRV_STA_SET_DPW.CNF",
+ "DRV_STA_SET_SL.CNF",
+ "DRV_STA_SET_M_STA_HFID.CNF",
+ "DRV_STA_SET_U_STA_HFID.CNF",
+ "DRV_STA_SET_AVLN_HFID.CNF",
+ "DRV_STA_SET_TONEMASK.CNF",
+ "DRV_STA_START.CNF",
+ "DRV_STA_STOP.CNF"
+};
+
+// this is the fmsn that will be used in fragmented mme
+static u8 fmsn_m;
+
+void msg_init(void)
+{
+#if DEBUG == 0
+ uint i;
+ for(i=1 ; i<COUNT(msg_list_m) ; i++)
+ dbg_assert(msg_list_m[i].mm_type > msg_list_m[i-1].mm_type);
+#endif
+ fmsn_m = 0;
+ msg_cm_init();
+}
+
+u8
+msg_get_fmsn(const bool new)
+{
+ printf ("%u %s()...\n",cyg_hal_sys_getpid(),__FUNCTION__);
+ // TODO the question is : is it possible to have 2 thread accessing this
+ // function at the same time ?
+ if(new) fmsn_m++;
+ return fmsn_m;
+}
+
+u16
+msg_get_number (msg_mme_t *msg)
+{
+ msg_mme_b_t * msg_b;
+ u16 mme_num;
+ u16 ret = MSG_UNKNOW;
+
+ printf ("%u %s() : DEBUT...\n",cyg_hal_sys_getpid(),__FUNCTION__);
+ dbg_assert ( !msg_check_wrong_mme_const_values (msg));
+ msg_b = (msg_mme_b_t *)msg;
+ printf ("%u %s() : VERIF... msg->m_type = 0x%04x ; msg_b->m_type = 0x%04x\n",cyg_hal_sys_getpid(),__FUNCTION__,big_to_cpuhost_endian_u16(msg->m_type),big_to_cpuhost_endian_u16(msg_b->m_type));
+ //TODO this is maybe not very efficient, to check with more messages ...
+ if (big_to_cpuhost_endian_u16(msg->m_type) == MSG_MTYPE_IEEE_ETHERTYPE)
+ {
+ printf ("%u %s() : DICHOTOMY sur msg->mm_type 0x%04x...\n",cyg_hal_sys_getpid(),__FUNCTION__,msg->mm_type);
+ DICHOTOMY_SEARCH(0, COUNT(msg_list_m), mme_num, msg->mm_type <= msg_list_m[mme_num].mm_type);
+ printf("%u requested msg : 0x%04x, index found : %i\n",cyg_hal_sys_getpid(), msg->mm_type, mme_num);
+ if(msg->mm_type != msg_list_m[mme_num].mm_type)
+ {
+ printf ("%u %s() : FIN. ; MSG_UNKNOW !\n",cyg_hal_sys_getpid(),__FUNCTION__);
+ ret = MSG_UNKNOW;
+ }
+ else
+ {
+ printf ("%u %s() : FIN. ; mme_num = %i (0x%04x)\n",cyg_hal_sys_getpid(),__FUNCTION__,mme_num,mme_num);
+ ret = mme_num;
+ }
+ }
+ else if ((big_to_cpuhost_endian_u16(msg_b->m_type) == MSG_MTYPE_IEEE_ETHERTYPE))
+ {
+ printf ("%u %s() : DICHOTOMY sur msg_b->mm_type 0x%04x...\n",cyg_hal_sys_getpid(),__FUNCTION__,msg_b->mm_type);
+ DICHOTOMY_SEARCH(0, COUNT(msg_list_m), mme_num, msg_b->mm_type <= msg_list_m[mme_num].mm_type);
+ printf ("%u requested msg : 0x%04x, index found : %i\n",cyg_hal_sys_getpid(), msg_b->mm_type, mme_num);
+ if(msg_b->mm_type != msg_list_m[mme_num].mm_type)
+ {
+ printf ("%u %s() : FIN. ; MSG_UNKNOW !\n",cyg_hal_sys_getpid(),__FUNCTION__);
+ ret = MSG_UNKNOW;
+ }
+ else
+ {
+ printf ("%u %s() : FIN. ; mme_num = %i (0x%04x)\n",cyg_hal_sys_getpid(),__FUNCTION__,mme_num,mme_num);
+ ret = mme_num;
+ }
+ }
+ else
+ {
+ printf ("%u %s() : FIN. ; ERREUR (mme_num = %i (0x%04x) !!!\n",cyg_hal_sys_getpid(),__FUNCTION__,mme_num,mme_num);
+ }
+ return ret;
+}
+
+//void
+//msg_dispatch (msg_mme_t *msg)
+void
+msg_dispatch (msg_ctx_t *msg_ctx)
+{
+ msg_mme_t *msg;
+ msg_mme_b_t *msg_b;
+ u16 mme_num;
+
+ printf ("%u %s() : DEBUT...\n",cyg_hal_sys_getpid(),__FUNCTION__);
+
+ dbg_assert(msg_ctx);
+ dbg_assert(msg_ctx->buffer);
+ msg = (msg_mme_t *)msg_ctx->buffer;
+ msg_b = (msg_mme_b_t *)msg;
+
+ dbg_assert ( !msg_check_wrong_mme_const_values (msg));
+ mme_num = msg_get_number (msg);
+ printf ("%u %s() : suite... ; mme_num = %i (0x%04x)\n",cyg_hal_sys_getpid(),__FUNCTION__,mme_num,mme_num);
+ if (mme_num != MSG_UNKNOW)
+ {
+ dbg_assert(msg_list_m[mme_num].msg_num);
+ cp_station_add_event(msg_list_m[mme_num].msg_num, (void *) msg_ctx);
+ }
+ // release the message's buffer(s)
+// interf_release_buf(msg);
+ printf ("%u %s() : FIN.\n",cyg_hal_sys_getpid(),__FUNCTION__);
+}
+
+void
+msg_set_mme_const_values (msg_mme_t *msg)
+{
+ dbg_assert (msg);
+
+ msg->m_type = cpuhost_to_big_endian_u16(MSG_MTYPE); // 11.1.4
+ msg->mmv = MSG_MM_VERSION;
+ #if CHECK_BUFFER_OVERFLOW
+ interf_buffer_t *buffer = NULL;
+ buffer = PARENT_OF(interf_buffer_t, msg, msg);
+ buffer->signature = BUFFER_SIGNATURE;
+ #endif
+}
+
+bool
+msg_check_wrong_mme_const_values (const msg_mme_t *msg)
+{int i; u8 *p = (u8*)msg;
+ msg_mme_b_t *msg_b;
+
+ printf ("%u %s()...\n",cyg_hal_sys_getpid(),__FUNCTION__);
+ for (i=0;i<1;i++)printf("msg = 0x%08lx ",(unsigned long)msg);printf("\n");
+ dbg_assert (msg);
+
+ msg_b = (msg_mme_b_t *)msg;
+
+ #if CHECK_BUFFER_OVERFLOW
+ interf_buffer_t *buffer = NULL;
+ buffer = PARENT_OF(interf_buffer_t, msg, msg);
+ dbg_assert(buffer->signature == BUFFER_SIGNATURE);
+ #endif
+
+ for (i= 0;i<16;i++)printf("%02x.",p[i]);printf("\n");
+ for (i=16;i<32;i++)printf("%02x.",p[i]);printf("\n");
+ for (i=32;i<48;i++)printf("%02x.",p[i]);printf("\n");
+ for (i=48;i<64;i++)printf("%02x.",p[i]);printf("\n");
+ printf("%u %s() : msg->m_type = 0x%04x\n",cyg_hal_sys_getpid(),__FUNCTION__,big_to_cpuhost_endian_u16(msg->m_type));
+ printf("%u %s() : msg_b->m_type = 0x%04x\n",cyg_hal_sys_getpid(),__FUNCTION__,big_to_cpuhost_endian_u16(msg_b->m_type));
+ if (big_to_cpuhost_endian_u16(msg->m_type) == MSG_MTYPE)
+ for (i=0;i<1;i++)printf("msg->m_type = 0x%04x ; msg->mm_type = 0x%04x",big_to_cpuhost_endian_u16(msg->m_type),msg->mm_type);
+ else if (big_to_cpuhost_endian_u16(msg_b->m_type) == MSG_MTYPE)
+ for (i=0;i<1;i++)printf("msg->m_type = 0x%04x ; msg->mm_type = 0x%04x",big_to_cpuhost_endian_u16(msg_b->m_type),msg_b->mm_type);
+ else
+ for (i=0;i<1;i++)printf("msg->m_type = 0x???? ; msg->mm_type = 0x????");
+ printf("\n");
+
+ return ((big_to_cpuhost_endian_u16(msg->m_type) != MSG_MTYPE) && (big_to_cpuhost_endian_u16(msg_b->m_type) != MSG_MTYPE));
+}
+
+msg_mme_t *
+msg_sending_common_part(msg_mme_t *msg, const mac_address_t oda, msg_param_t *msg_param)
+{
+ dbg_assert(msg);
+ dbg_assert(msg_param);
+
+ // ask for a buffer
+ //msg = interf_give_buf ();
+ //dbg_assert ( !msg_check_wrong_mme_const_values (msg));
+ // set the header values of msg
+ memcpy(msg->oda, oda, sizeof(mac_address_t));
+ //memcpy(msg->osa, station_get_mac_address(), sizeof(mac_address_t));
+ cp_station_get_mac_address(NULL,&msg->osa); //TODO : pass CP ctx as first argument instead of NULL pointer...
+ // vlan is optional and not used
+ msg->m_type = cpuhost_to_big_endian_u16(MSG_MTYPE); // 11.1.4
+ msg->mmv = MSG_MM_VERSION;
+ // set fragmentation default values
+ msg->fmi.nf_mi = 0;
+ msg->fmi.fn_mi = 0;
+ msg->fmi.fmsn = 0;
+ // set the default message parameters
+ memset(msg_param, 0, sizeof(msg_param_t));
+ msg_param->encryption = HARDWARE_ENCRYPTED;
+ msg_param->peks = NOT_ENCRYPTED;
+ return msg;
+}
+
+void
+msg_send(msg_mme_t *msg, u16 msg_size, msg_param_t msg_param)
+{
+ tei_t tei;
+
+ dbg_assert ( !msg_check_wrong_mme_const_values (msg));
+ dbg_assert(msg_size <= ETH_PACKET_MAX_SIZE);
+
+ // find the tei of the ODA
+ tei = cp_station_find_tei_from_mac(msg->oda);
+ // check if the message is software encrypted
+ if(msg_param.encryption == SOFTWARE_ENCRYPTED)
+ {
+
+ }
+ else
+ {
+ // and then, send the message
+ interf_send (msg, msg_size, msg_param, tei);
+ }
+}
+
+/**
+ * \brief Get DRV-MME .REQ message name
+ *
+ * \param cnf the REQ message type identifier
+ * \return the .REQ message name string constant
+ */
+char *
+get_str_drv_mme_req(int req)
+{
+ return (char*)cst_str_drv_mme_req[req];
+}
+
+/**
+ * \brief Get DRV-MME .CNF message name
+ *
+ * \param cnf the CNF message type identifier
+ * \return the .CNF message name string constant
+ */
+char *
+get_str_drv_mme_cnf(int cnf)
+{
+ return (char*)cst_str_drv_mme_cnf[cnf];
+}
+
+#if 0
+/**
+ * \brief Get a message type name string
+ *
+ * \param mmtype the message type identifier
+ * \return the message type name string constant
+ */
+char *
+get_str_mmtype(u16 mmtype)
+{
+ return (char*)cst_str_drv_mme_cnf[cnf];
+}
+#endif
diff --git a/cesar/cp/msg/src/msg_apcm.c b/cesar/cp/msg/src/msg_apcm.c
new file mode 100644
index 0000000000..9aee40a5c3
--- /dev/null
+++ b/cesar/cp/msg/src/msg_apcm.c
@@ -0,0 +1,16 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}}
+ * \file msg_apcm.c
+ * \brief File Description
+ * \ingroup cp/msg
+ *
+ */
+
+#include "common/std.h"
+
+
diff --git a/cesar/cp/msg/src/msg_cc.c b/cesar/cp/msg/src/msg_cc.c
new file mode 100644
index 0000000000..cdee5d9a46
--- /dev/null
+++ b/cesar/cp/msg/src/msg_cc.c
@@ -0,0 +1,141 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/msg/msg_cc.c
+ * \brief
+ * \ingroup cp_msg
+ */
+
+#include "common/std.h"
+
+#include "cp/beacon/inc/bentry.h"
+#include "cp/beacon/inc/beacons_ctx.h"
+#include "cp/beacon/forward.h"
+#include "cp/beacon/inc/beacons_work.h"
+
+#include "cp/msg/inc/msg_cc.h"
+
+
+
+void msg_cc_assoc_req_send(const mac_address_t oda)
+{
+/* msg_mme_t *msg;
+ cc_assoc_req_t *cc_assoc_req;
+ msg_param_t msg_param;
+
+ msg = msg_sending_common_part(oda, &msg_param);
+ msg->mm_type = CC_ASSOC_REQ;
+ // set the message values ( 11.2.28 )
+ cc_assoc_req = (cc_assoc_req_t *) & msg->mm_entry;
+ cc_assoc_req->cco_capability = station_get_cco_capa();
+ cc_assoc_req->nid = station_get_nid();
+ cc_assoc_req->proxy_networking_capability = 0;
+ cc_assoc_req->req_type = 0;
+ // set the message parameters
+ msg_param.encryption = NOT_ENCRYPTED;
+ // and then, send the message
+ msg_send(msg, sizeof(cc_assoc_req_t) + MSG_MME_HEADER_SIZE, msg_param);
+ */
+}
+
+void msg_cc_assoc_cnf_send(const mac_address_t oda, const u8 result, const tei_t sta_tei, const u16 lease_time)
+{
+/* msg_mme_t *msg;
+ cc_assoc_cnf_t *cc_assoc_cnf;
+ msg_param_t msg_param;
+
+ msg = msg_sending_common_part(oda, &msg_param);
+ msg->mm_type = CC_ASSOC_CNF;
+ // set the message values ( 11.2.29 )
+ cc_assoc_cnf = (cc_assoc_cnf_t *) & msg->mm_entry;
+ cc_assoc_cnf->result = result;
+ cc_assoc_cnf->nid = station_get_nid();
+ cc_assoc_cnf->snid = station_get_snid();
+ cc_assoc_cnf->sta_tei = sta_tei;
+ cc_assoc_cnf->lease_time = lease_time;
+ // set the message parameters
+ msg_param.encryption = NOT_ENCRYPTED;
+ // and then, send the message
+ msg_send(msg, sizeof(cc_assoc_cnf_t) + MSG_MME_HEADER_SIZE, msg_param);
+*/
+}
+
+void
+msg_cc_set_tei_map_ind_send(const mac_address_t oda, const u8 mode, const tei_t tei, const bool recall)
+{/*
+ // 11.2.35
+ msg_mme_t *msg;
+ cc_set_tei_map_ind_t *cc_set_tei_map_ind;
+ msg_param_t msg_param;
+ u8 number_sta;
+ int i;
+ static tei_t m_tei;
+ tei_t next_tei;
+ station_t sta;
+
+ // TODO remove printf
+ //printf("msg_cc_set_tei_map_ind_send oda : %c%c%c%c%c%c, mode : %i\n", oda[0], oda[1], oda[2], oda[3], oda[4], oda[5], mode);
+ msg = msg_sending_common_part(oda, &msg_param);
+ msg->mm_type = CC_SET_TEI_MAP_IND;
+ // set the message values ( 11.2.35 )
+ cc_set_tei_map_ind = (cc_set_tei_map_ind_t *) & msg->mm_entry;
+ cc_set_tei_map_ind->mode = mode;
+ if(mode == 0)
+ {
+ msg_param.encryption = NOT_ENCRYPTED;
+ number_sta = station_get_number_of_assoc();
+ if( ! recall)
+ {
+ // first time that the function is called
+ if(number_sta < SET_TEI_MAP_SUB_NB_ELEM)
+ {
+ cc_set_tei_map_ind->num = number_sta;
+ }
+ else
+ {
+ msg->fmi.nf_mi = 1;
+ msg->fmi.fn_mi = 0;
+ msg->fmi.fmsn = msg_get_fmsn(true);
+ cc_set_tei_map_ind->num = SET_TEI_MAP_SUB_NB_ELEM;
+ }
+ }
+ else
+ {
+ cc_set_tei_map_ind->num = number_sta - SET_TEI_MAP_SUB_NB_ELEM;
+ msg->fmi.nf_mi = 1;
+ msg->fmi.fn_mi = 1;
+ msg->fmi.fmsn = msg_get_fmsn(false);
+ }
+ }
+ else // mode != 0
+ {
+ msg_param.encryption = HARDWARE_ENCRYPTED;
+ number_sta = 1;
+ cc_set_tei_map_ind->num = 1;
+ }
+ if( ! recall) m_tei = tei;
+ for(i=0 ; i<number_sta ; i++)
+ {
+ if( ( ! tei) && ( ! i ) && ( ! recall) )
+ next_tei = station_get_associate_info(&sta, true , 0);
+ else
+ next_tei = station_get_associate_info(&sta, false , m_tei);
+ memcpy(cc_set_tei_map_ind->sub[i].mac_address, sta.mac_address, sizeof(mac_address_t));
+ if(sta.station_status == STATION_ASSOCIATED)
+ cc_set_tei_map_ind->sub[i].status = 0x0;
+ else cc_set_tei_map_ind->sub[i].status = 0x1;
+ cc_set_tei_map_ind->sub[i].tei = m_tei;
+ m_tei = next_tei;
+ }
+ // set the message parameters
+ //msg_param.mnbf = 0;
+ // and then, send the message
+ msg_send(msg, MSG_MME_HEADER_SIZE + 2 + number_sta * sizeof(cc_set_tei_map_ind_sub_t), msg_param);
+*/
+}
+
diff --git a/cesar/cp/msg/src/msg_cm.c b/cesar/cp/msg/src/msg_cm.c
new file mode 100644
index 0000000000..3795fe2828
--- /dev/null
+++ b/cesar/cp/msg/src/msg_cm.c
@@ -0,0 +1,273 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/msg/msg_cm.c
+ * \brief
+ * \ingroup cp_msg
+ */
+
+#include "common/std.h"
+
+#include "cp/beacon/inc/bentry.h"
+#include "cp/beacon/inc/beacons_ctx.h"
+#include "cp/beacon/forward.h"
+#include "cp/beacon/inc/beacons_work.h"
+
+#include "cp/msg/inc/msg_cm.h"
+#include "lib/crc.h"
+
+
+static crc_t crc_m;
+static u32 *crc_table[256];
+
+void
+msg_cm_init(void)
+{
+ // init the CRC context (CRC used in cm_encrypted_payload)
+ crc_m.width = 32;
+ crc_m.generator = 0x4C11DB7; //4.2.1
+ crc_m.init = 0xFFFFFFFF;
+ crc_m.refin = true;
+ crc_m.refout = true;
+ crc_m.xorout = 0xFFFFFFFF;
+ crc_m.table.t32 = (u32 *) crc_table;
+ crc_m.reg_init = 0;
+ crc_init(&crc_m);
+}
+
+void
+msg_cm_unassociated_sta_ind_send(const mac_address_t oda)
+{
+ // 11.5.1
+ msg_mme_t *msg_p, *msg_to_send;
+ cm_unassociated_sta_t *unassociated_sta_p;
+ msg_param_t msg_param;
+ u8 buffer[1518];
+
+ msg_p = msg_sending_common_part((msg_mme_t *)buffer, oda, &msg_param);
+ msg_p->mm_type = CM_UNASSOCIATED_STA_IND;
+ // set the message values
+ unassociated_sta_p = (cm_unassociated_sta_t *) & msg_p->mm_entry;
+ unassociated_sta_p->nid = cp_station_get_nid(NULL); //TODO : pass CP ctx as first argument instead of NULL pointer...
+ unassociated_sta_p->cco_capability = cp_station_get_cco_capa();
+ // set the mnbf flag
+ msg_param.mnbf = 1;
+ msg_param.encryption = NOT_ENCRYPTED;
+ // and finaly, send the message
+ printf(" send cm_unassociated_sta\n");
+ msg_to_send = interf_give_buf ();
+ dbg_assert ( !msg_check_wrong_mme_const_values (msg_to_send));
+ //msg_cm_unassociated_sta_ind_convert((u8 *)msg_to_send, msg_p, BITSTREAM_WRITE);
+ msg_send(msg_p, sizeof(cm_unassociated_sta_t) + MSG_MME_HEADER_SIZE, msg_param);
+}
+
+// set the following flag to 1 if you want to
+// test the message as on page 681
+#define TEST_681 0
+
+void
+msg_cm_encrypted_payload_ind_send(
+ const msg_mme_t *encapsulated_msg_p,
+ const msg_param_t encapsulated_msg_param,
+ const tei_t tei,
+ const bool last_msg_of_p_run,
+ const cp_pid_t pid,
+ const u16 msg_size
+ )
+{
+ // 11.5.2
+ msg_mme_t *msg_p;
+ cm_encrypted_payload_t *cm_encrypted_payload_p;
+ cm_encrypted_payload_sub_t *cm_encrypted_payload_sub_p;
+ msg_param_t msg_param;
+ cp_station_status_t station_status;
+ protocol_run_t pr_run;
+ u8 rf, i, pad_size;
+ aes_key_t *aes_key_p;
+ aes_context ctx;
+ u16 total_msg_size = msg_size + sizeof(cm_encrypted_payload_t) - COUNT(cm_encrypted_payload_p->rf) + 9;
+ u8 buffer[1518], data_to_encrypt[1518];
+ int *int_p;
+ u8 iv[16];
+
+ dbg_assert ( !msg_check_wrong_mme_const_values (encapsulated_msg_p));
+ dbg_assert(tei != 0 && tei != 0xFF);
+ dbg_assert(pid <= HLE_PRO);
+ dbg_assert(msg_size < (sizeof(msg_mme_t) - sizeof(cm_encrypted_payload_t) - sizeof(cm_encrypted_payload_sub_t)));
+
+
+ msg_p = msg_sending_common_part((msg_mme_t *)buffer, encapsulated_msg_p->oda, &msg_param);
+ msg_p->mm_type = CM_ENCRYPTED_PAYLOAD_IND;
+ // set the message values
+ cm_encrypted_payload_p = (cm_encrypted_payload_t *) & msg_p->mm_entry;
+ // set the message values...
+ cm_encrypted_payload_p->peks = encapsulated_msg_param.peks;
+ // set the avln status of the station
+ station_status = cp_station_get_status();
+ #if TEST_681
+ station_status = 5;
+ #endif
+ if(station_status == STATION_UNASSOCIATED)
+ {
+ cm_encrypted_payload_p->avln_status = cp_station_get_cco_capa();
+ }
+ else
+ {
+ if(cp_station_get_is_cco())
+ {
+ cm_encrypted_payload_p->avln_status = 0x08;
+ }
+ else
+ {
+ // the station is assosciated
+ cm_encrypted_payload_p->avln_status = 0x04;
+ if(cp_station_get_pcco_capa()) cm_encrypted_payload_p->avln_status = 0x05;
+ }
+ }
+ // set the protocol run parameters
+ if(secu_gen_protocol_run_param(tei, last_msg_of_p_run, &pr_run) == PRN_NotInitialised)
+ {
+ secu_start_new_protocol_run(tei, pid, &pr_run);
+ secu_gen_protocol_run_param(tei, last_msg_of_p_run, &pr_run);
+ #if TEST_681
+ pr_run.pmn = 3;
+ pr_run.prn = 0x372D;
+ #endif
+ }
+ cm_encrypted_payload_p->pid = pr_run.pid;
+ cm_encrypted_payload_p->prn = pr_run.prn;
+ cm_encrypted_payload_p->pmn = pr_run.pmn;
+ cm_encrypted_payload_p->len = msg_size;
+ if(pid == HLE_PRO) // case PID == 0x4
+ {
+ // calculate the UUID field as specified in rfc4122 chap 4.4
+ int_p = (int *)cm_encrypted_payload_p->iv;
+ for(i=0 ; i<4 ; i++)
+ {
+ *int_p = rand_in(0, 0);
+ int_p++;
+ }
+ cm_encrypted_payload_p->iv[8] &= 0xBF;
+ cm_encrypted_payload_p->iv[8] |= 0x80;
+ cm_encrypted_payload_p->iv[6] = 0x4;
+ cm_encrypted_payload_p->iv[7] = 0x0;
+ // case PID == 0x4 implies no random filer
+ rf = 0;
+ memcpy(cm_encrypted_payload_p->rf, encapsulated_msg_p, msg_size);
+ }
+ else
+ {
+ // set the IV field (16 random bytes)
+ int_p = (int *) iv;
+ for(i=0 ; i<4 ; i++)
+ {
+ *int_p = rand_in(0, 0);
+ int_p++;
+ }
+ #if TEST_681
+ memcpy(iv, "\xFE\xDC\xBA\x98\x76\x54\x32\x10\xFE\xDC\xBA\x98\x76\x54\x32\x10", 16);
+ #endif
+ memcpy(cm_encrypted_payload_p->iv, iv, 16);
+ // calculate the rf filler size
+ rf = rand_in(0, COUNT(cm_encrypted_payload_p->rf));
+ // fill the rf field with random data
+ for(i=0 ; i<rf ; i++)
+ data_to_encrypt[i] = (u8) rand_in(0, 0xFF);
+ #if TEST_681
+ rf = 5;
+ data_to_encrypt[0] = 0x24;
+ data_to_encrypt[1] = 0x68;
+ data_to_encrypt[2] = 0xac;
+ data_to_encrypt[3] = 0xe0;
+ data_to_encrypt[4] = 0x35;
+ #endif
+ memcpy(&data_to_encrypt[rf], encapsulated_msg_p, msg_size);
+ cm_encrypted_payload_sub_p = (cm_encrypted_payload_sub_t *) &data_to_encrypt[i+msg_size];
+ // calculate CRC of the encapsulated mme
+ cm_encrypted_payload_sub_p->crc = crc_compute_block(&crc_m, (u8 *)encapsulated_msg_p, msg_size);
+ cm_encrypted_payload_sub_p->pid = pid;
+ cm_encrypted_payload_sub_p->prn = pr_run.prn;
+ cm_encrypted_payload_sub_p->pmn = pr_run.pmn;
+ pad_size = 16 - (msg_size + rf + 9) % 16;
+ for(i=0 ; i < pad_size ; i++)
+ cm_encrypted_payload_sub_p->padding[i] = (u8) rand_in(0, 0xFF);
+ #if TEST_681
+ cm_encrypted_payload_sub_p->padding[0] = 0xac ;
+ cm_encrypted_payload_sub_p->padding[1] = 0xbc ;
+ cm_encrypted_payload_sub_p->padding[2] = 0xd2 ;
+ cm_encrypted_payload_sub_p->padding[3] = 0x11 ;
+ cm_encrypted_payload_sub_p->padding[4] = 0x4d ;
+ cm_encrypted_payload_sub_p->padding[5] = 0xae ;
+ cm_encrypted_payload_sub_p->padding[6] = 0x15 ;
+ cm_encrypted_payload_sub_p->padding[7] = 0x77 ;
+ cm_encrypted_payload_sub_p->padding[8] = 0xc6 ;
+ #endif
+ cm_encrypted_payload_sub_p->padding[i] = rf;
+ aes_key_p = secu_get_ek_from_peks(encapsulated_msg_param.peks, tei);
+ aes_set_key(&ctx, (u8 *) aes_key_p, sizeof(aes_key_t)*8);
+ aes_cbc_encrypt (&ctx, iv, data_to_encrypt, cm_encrypted_payload_p->rf+rf, rf+msg_size+pad_size+9);
+ total_msg_size += rf + pad_size;
+ }
+ // set the mnbf flag
+ msg_param.encryption = NOT_ENCRYPTED;
+ // and finaly, send the message
+ msg_send(msg_p, total_msg_size, msg_param);
+
+}
+
+
+/*
+void
+msg_cm_conn_new_req_send(msg_cm_conn_new_req_t msg)
+{
+ // msg_mme_t *msg;
+ // cm_conn_new_req_t
+}
+
+void
+msg_cm_conn_new_cnf_send()
+{
+
+}
+
+void
+msg_cm_conn_rel_ind_send()
+{
+
+}
+
+void
+msg_cm_conn_rel_rsp_send()
+{
+
+}
+
+void
+msg_cm_conn_mod_req_send()
+{
+
+}
+
+void
+msg_cm_conn_mod_cnf_send()
+{
+
+}
+
+void
+msg_cm_conn_info_req_send()
+{
+
+}
+
+void
+msg_cm_conn_info_cnf_send()
+{
+
+}
+*/
diff --git a/cesar/cp/msg/src/msg_cm_convert.c b/cesar/cp/msg/src/msg_cm_convert.c
new file mode 100644
index 0000000000..b009db35f5
--- /dev/null
+++ b/cesar/cp/msg/src/msg_cm_convert.c
@@ -0,0 +1,65 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/msg/msg_cm.c
+ * \brief
+ * \ingroup cp_msg
+ */
+
+#include "common/std.h"
+
+#include "cp/beacon/inc/bentry.h"
+#include "cp/beacon/inc/beacons_ctx.h"
+#include "cp/beacon/forward.h"
+#include "cp/beacon/inc/beacons_work.h"
+
+#include "cp/msg/inc/msg_cm_convert.h"
+
+void
+msg_mme_header_convert(u8 *buffer, msg_mme_t *msg, bitstream_type_t b_type, bitstream_t ctx)
+{/*
+ dbg_assert(buffer);
+ dbg_assert(msg);
+ u8 tmp;
+
+ bitstream_access(&ctx, &msg->oda, 48);
+ bitstream_access(&ctx, &msg->osa, 48);
+ //bitstream_access(&ctx, &msg->v_lan_tag, 32);
+ bitstream_access(&ctx, &msg->m_type, 16);
+ bitstream_access(&ctx, &msg->mmv, 8);
+ bitstream_access(&ctx, &msg->mm_type, 16);
+ tmp = msg->fmi.nf_mi;
+ bitstream_access(&ctx, &tmp, 4);
+ if(b_type == BITSTREAM_READ) msg->fmi.nf_mi = tmp;
+ tmp = msg->fmi.fn_mi;
+ bitstream_access(&ctx, &tmp, 4);
+ if(b_type == BITSTREAM_READ) msg->fmi.fn_mi = tmp;
+ bitstream_access(&ctx, &msg->fmi.fmsn, 8);
+*/
+}
+
+void
+msg_cm_unassociated_sta_ind_convert(u8 *buffer, msg_mme_t *msg, bitstream_type_t read)
+{// 11.5.1
+
+ bitstream_t ctx;
+ cm_unassociated_sta_t *entry_p;
+
+ dbg_assert(buffer);
+ dbg_assert(msg);
+
+ bitstream_init(&ctx, buffer, 1518, read);
+
+ msg_mme_header_convert(buffer, msg, read, ctx);
+ entry_p = ( cm_unassociated_sta_t *) msg->mm_entry;
+ bitstream_access(&ctx, &entry_p->nid, 2); // this is just to read the 2 non significant bits
+ bitstream_access(&ctx, &entry_p->nid, 54);
+ bitstream_access(&ctx, &entry_p->cco_capability, 1);
+
+ bitstream_finalise(&ctx); // don't forget it to write the last word
+}
diff --git a/cesar/cp/msg/src/msg_drv.c b/cesar/cp/msg/src/msg_drv.c
new file mode 100644
index 0000000000..60533040a5
--- /dev/null
+++ b/cesar/cp/msg/src/msg_drv.c
@@ -0,0 +1,497 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file cp/msg/src/msg_drv.c
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+#include <stdio.h>
+#include <string.h>
+#include "common/std.h"
+#include "lib/bitstream.h"
+#include "cp/secu/inc/secu_types.h"
+#include "cp/msg/inc/msg_const.h"
+#include "cp/msg/inc/msg_drv.h"
+
+const char *cst_str_drv_mme_cnf_result[] = {
+ "FAILURE",
+ "SUCCESS"
+};
+
+const char *cst_str_drv_mme_cnf_errcode[] = {
+ "BAD PARAMETER",
+ "UNKNOWN ID",
+ "INVALID VALUE"
+};
+
+const char *cst_str_yes_no[] = {
+ "no",
+ "yes"
+};
+
+
+/**
+ * \brief Get DRV-MME .CNF message result string
+ *
+ * \param cnf_result the result code
+ * \return the result code string constant
+ */
+char *
+get_str_drv_mme_cnf_result(int cnf_result)
+{
+ return (char*)cst_str_drv_mme_cnf_result[cnf_result];
+}
+
+/**
+ * \brief Get DRV-MME .CNF message error code string
+ *
+ * \param cnf_errcode the error code
+ * \return the error code string constant
+ */
+char *
+get_str_drv_mme_cnf_errcode(int cnf_errcode)
+{
+ return (char*)cst_str_drv_mme_cnf_errcode[cnf_errcode];
+}
+
+/**
+ * \brief Get yes/no string.
+ *
+ * \param no_yes the index of yes/no string array
+ * \return the yes or no string constant
+ */
+char *
+get_str_yes_no(int no_yes)
+{
+ return (char*)cst_str_yes_no[no_yes];
+}
+
+/**
+ * \brief Verify a password or HFID string validity.
+ *
+ * \param str the HFID string to be verified
+ * \param minlen the minimal length
+ * \param maxlen the maximal length
+ * \return true or false depending on validity ok or not
+ */
+bool
+check_password_or_hfid_is_valid(char *str, int minlen,int maxlen)
+{
+ int i;
+
+ if (((int)strlen(str) < minlen) || ((int)strlen(str) > maxlen)) return false;
+
+ for (i = 0; i < (int)strlen(str); i++)
+ {
+ if (((u8)str[i] < MIN_PWD_ASCII_CHAR) || ((u8)str[i] > MAX_PWD_ASCII_CHAR))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * \brief little endian to CPU host endian conversion.
+ *
+ * \param addrval pointer to the value to be (re)formatted from little endian to CPU host endian
+ * \param bytesizeval the size in bytes of the value
+ */
+void
+little_to_cpuhost_endian(u8 *addrval, int bytesizeval)
+{
+ u8 c;
+ int i;
+ union {
+ u32 u32;
+ u8 b[4];
+ } cpuarch;
+
+ cpuarch.u32 = 1;
+ if (cpuarch.b[0] != 1)
+ {
+ //printf("BIG-ENDIAN CPU...\n");
+ for (i = 0; i < (bytesizeval / 2); i++)
+ {
+ c = addrval[i];
+ addrval[i] = addrval[bytesizeval-1-i];
+ //printf("[%d] <- 0x%02X ; [%d] <- 0x%02X\n",i,addrval[bytesizeval-1-i],bytesizeval-1-i,c);
+ addrval[bytesizeval-1-i] = c;
+ }
+ }
+}
+
+/**
+ * \brief big endian to CPU host endian conversion.
+ *
+ * \param addrval pointer to the value to be (re)formatted from big endian to CPU host endian
+ * \param bytesizeval the size in bytes of the value
+ */
+void
+big_to_cpuhost_endian(u8 *addrval, int bytesizeval)
+{
+ u8 c;
+ int i;
+ union {
+ u32 u32;
+ u8 b[4];
+ } cpuarch;
+
+ cpuarch.u32 = 1;
+ if (cpuarch.b[0] == 1)
+ {
+ //printf("LITTLE-ENDIAN CPU...\n");
+ for (i = 0; i < (bytesizeval / 2); i++)
+ {
+ c = addrval[i];
+ addrval[i] = addrval[bytesizeval-1-i];
+ //printf("[%d] <- 0x%02X ; [%d] <- 0x%02X\n",i,addrval[bytesizeval-1-i],bytesizeval-1-i,c);
+ addrval[bytesizeval-1-i] = c;
+ }
+ }
+}
+
+/**
+ * \brief CPU host endian to little endian conversion.
+ *
+ * \param addrval pointer to the value to be (re)formatted from CPU host endian to little endian
+ * \param bytesizeval the size in bytes of the value
+ */
+void
+cpuhost_to_little_endian(u8 *addrval, int bytesizeval)
+{
+ u8 c;
+ int i;
+ union {
+ u32 u32;
+ u8 b[4];
+ } cpuarch;
+
+ cpuarch.u32 = 1;
+ if (cpuarch.b[0] != 1)
+ {
+ //printf("BIG-ENDIAN CPU...\n");
+ for (i = 0; i < (bytesizeval / 2); i++)
+ {
+ c = addrval[i];
+ addrval[i] = addrval[bytesizeval-1-i];
+ //printf("[%d] <- 0x%02X ; [%d] <- 0x%02X\n",i,addrval[bytesizeval-1-i],bytesizeval-1-i,c);
+ addrval[bytesizeval-1-i] = c;
+ }
+ }
+}
+
+/**
+ * \brief CPU host endian to big endian conversion.
+ *
+ * \param addrval pointer to the value to be (re)formatted from CPU host endian to big endian
+ * \param bytesizeval the size in bytes of the value
+ */
+void
+cpuhost_to_big_endian(u8 *addrval, int bytesizeval)
+{
+ u8 c;
+ int i;
+ union {
+ u32 u32;
+ u8 b[4];
+ } cpuarch;
+
+ cpuarch.u32 = 1;
+ if (cpuarch.b[0] == 1)
+ {
+ //printf("LITTLE-ENDIAN CPU...\n");
+ for (i = 0; i < (bytesizeval / 2); i++)
+ {
+ c = addrval[i];
+ addrval[i] = addrval[bytesizeval-1-i];
+ //printf("[%d] <- 0x%02X ; [%d] <- 0x%02X\n",i,addrval[bytesizeval-1-i],bytesizeval-1-i,c);
+ addrval[bytesizeval-1-i] = c;
+ }
+ }
+}
+
+u16
+big_to_cpuhost_endian_u16(u16 val)
+{
+ u16 ret = val;
+ big_to_cpuhost_endian((u8 *)&ret, sizeof(ret));
+ return ret;
+}
+
+u32
+big_to_cpuhost_endian_u32(u32 val)
+{
+ u32 ret = val;
+ big_to_cpuhost_endian((u8 *)&ret, sizeof(ret));
+ return ret;
+}
+
+u16
+cpuhost_to_big_endian_u16(u16 val)
+{
+ u16 ret = val;
+ cpuhost_to_big_endian((u8 *)&ret, sizeof(ret));
+ return ret;
+}
+
+u32
+cpuhost_to_big_endian_u32(u32 val)
+{
+ u32 ret = val;
+ cpuhost_to_big_endian((u8 *)&ret, sizeof(ret));
+ return ret;
+}
+
+void display_mme_header(mme_header_type *mme_header)
+{
+ printf ("%u /*\t0x%08x : osa ........ 0x%012llX => @MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ cyg_hal_sys_getpid(),
+ (unsigned int)&mme_header->un_osa,
+ mme_header->un_osa.u64,
+ (u8)((mme_header->un_osa.u64 & 0xFF0000000000ULL) >> 40),
+ (u8)((mme_header->un_osa.u64 & 0x00FF00000000ULL) >> 32),
+ (u8)((mme_header->un_osa.u64 & 0x0000FF000000ULL) >> 24),
+ (u8)((mme_header->un_osa.u64 & 0x000000FF0000ULL) >> 16),
+ (u8)((mme_header->un_osa.u64 & 0x00000000FF00ULL) >> 8),
+ (u8) (mme_header->un_osa.u64 & 0x0000000000FFULL)
+ );
+ printf ("%u /*\t0x%08x : oda ........ 0x%012llX => @MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ cyg_hal_sys_getpid(),
+ (unsigned int)&mme_header->un_oda,
+ mme_header->un_oda.u64,
+ (u8)((mme_header->un_oda.u64 & 0xFF0000000000ULL) >> 40),
+ (u8)((mme_header->un_oda.u64 & 0x00FF00000000ULL) >> 32),
+ (u8)((mme_header->un_oda.u64 & 0x0000FF000000ULL) >> 24),
+ (u8)((mme_header->un_oda.u64 & 0x000000FF0000ULL) >> 16),
+ (u8)((mme_header->un_oda.u64 & 0x00000000FF00ULL) >> 8),
+ (u8) (mme_header->un_oda.u64 & 0x0000000000FFULL)
+ );
+ if (mme_header->vlan_tag_flag == true)
+ {
+ printf
+ ("%u /*\t0x%08x : vlan_tag ... 0x%04X 0x%04X",
+ cyg_hal_sys_getpid(),
+ (unsigned int)&mme_header->un_vlan_tag,
+ (u16)(mme_header->un_vlan_tag.u32 >> 16),
+ (u16)(mme_header->un_vlan_tag.u32 & 0x0000FFFF));
+ if ((u16)(mme_header->un_vlan_tag.u32 >> 16) == MSG_VLAN_TAG_IEEE_802_1Q)
+ printf(" => IEEE 802.1Q VLAN Tag\n");
+ else
+ printf(" => UNKNOWN/UNEXPECTED !?\n");
+ }
+ printf ("%u /*\t0x%08x : mtype ...... 0x%04lX",
+ cyg_hal_sys_getpid(),
+ (unsigned int)&mme_header->un_mtype,
+ mme_header->un_mtype.u32);
+ if (mme_header->un_mtype.u32 == MSG_MTYPE_IEEE_ETHERTYPE)
+ printf(" => IEEE ETHERTYPE\n");
+ else
+ printf(" => UNKNOWN/UNEXPECTED !?\n");
+ printf ("%u /*\t0x%08x : mmv ........ 0x%02lX (%lu) => HomePlug AV 1.%lu specification\n",
+ cyg_hal_sys_getpid(),
+ (unsigned int)&mme_header->un_mmv,
+ mme_header->un_mmv.u32,mme_header->un_mmv.u32,
+ mme_header->un_mmv.u32);
+ printf ("%u /*\t0x%08x : mmtype ..... 0x%04lX",
+ cyg_hal_sys_getpid(),
+ (unsigned int)&mme_header->un_mmtype,
+ mme_header->un_mmtype.u32);
+
+ switch(mme_header->un_mmtype.u32)
+ {
+ case DRV_STA_SET_MAC_ADDR_REQ :
+ case DRV_STA_SET_CCO_PREF_REQ :
+ case DRV_STA_SET_WAS_CCO_REQ :
+ case DRV_STA_SET_NPW_REQ :
+ case DRV_STA_SET_DPW_REQ :
+ case DRV_STA_SET_SL_REQ :
+ case DRV_STA_SET_M_STA_HFID_REQ :
+ case DRV_STA_SET_U_STA_HFID_REQ :
+ case DRV_STA_SET_AVLN_HFID_REQ :
+ case DRV_STA_SET_TONEMASK_REQ :
+ case DRV_STA_START_REQ :
+ case DRV_STA_STOP_REQ :
+ printf(" => %s\n",get_str_drv_mme_req((mme_header->un_mmtype.u32-DRV_STA_SET_MAC_ADDR_REQ)/4));
+ break;
+ case DRV_STA_SET_MAC_ADDR_CNF :
+ case DRV_STA_SET_CCO_PREF_CNF :
+ case DRV_STA_SET_WAS_CCO_CNF :
+ case DRV_STA_SET_NPW_CNF :
+ case DRV_STA_SET_DPW_CNF :
+ case DRV_STA_SET_SL_CNF :
+ case DRV_STA_SET_M_STA_HFID_CNF :
+ case DRV_STA_SET_U_STA_HFID_CNF :
+ case DRV_STA_SET_AVLN_HFID_CNF :
+ case DRV_STA_SET_TONEMASK_CNF :
+ case DRV_STA_START_CNF :
+ case DRV_STA_STOP_CNF :
+ printf(" => %s\n",get_str_drv_mme_cnf((mme_header->un_mmtype.u32-DRV_STA_SET_MAC_ADDR_CNF)/4));
+ break;
+ default :
+ printf("\n");
+ break;
+ }
+ printf ("%u /*\t0x%08x : fmi ........ 0x%04lX => MMENTRY fragment %lu/%lu, FNSM = 0x%02lX (%lu)\n",
+ cyg_hal_sys_getpid(),
+ (unsigned int)&mme_header->un_fmi,
+ mme_header->un_fmi.u32,
+ ((mme_header->un_fmi.u32 & 0xF000) >> 12)+1,
+ ((mme_header->un_fmi.u32 & 0xF00) >> 8)+1,
+ mme_header->un_fmi.u32 & 0xFF,
+ mme_header->un_fmi.u32 & 0xFF);
+}
+
+/**
+ * \brief Build a "MME.CNF" confirmation message.
+ *
+ * \param recv_mme_header the buffer to contain the MME.CNF message being built
+ * \param send_mme the buffer containing the MME initially received for which we're building a CNF
+ * \param cnf_result the result code of the MME.CNF message to be built
+ * \param cnf_errcode the error code of the MME.CNF message to be built
+ * \param cnf_len the returned length of the MME.CNF message being built
+ *
+ */
+void
+cp_mme_build_cnf (mme_header_type *recv_mme_header, mme_drv_cnf_type *send_mme, e_drv_mme_cnf_result cnf_result, e_drv_mme_cnf_errcode cnf_errcode, uint *cnf_len, u8 *mme_tx_buffer, int *mme_buffer_first)
+{
+ bitstream_t bstr_ctx;
+ uint pld_maxlen;
+ uint i, j;
+
+ printf ("%u %s() : mme_tx_buffer = 0x%08lx\n",cyg_hal_sys_getpid(),__FUNCTION__,(unsigned long)mme_tx_buffer);
+
+ /* Prepare CNF message to be sent back to OSA */
+ send_mme->header = *recv_mme_header;
+ send_mme->header.un_osa.u64 = recv_mme_header->un_oda.u64;
+ send_mme->header.un_oda.u64 = recv_mme_header->un_osa.u64;
+ send_mme->header.un_mmtype.u32 |= CNF;
+
+ /* TODO : don't reset the VLAN tag field, keep the one of the incoming message header... */
+ send_mme->header.un_vlan_tag.u32 = 0x00000000;
+
+ /* TODO : fill & format the FMI field... */
+ send_mme->header.un_fmi.u32 = 0x00000000;
+
+ printf ("%u /* MME HEADER :\n",cyg_hal_sys_getpid());
+ display_mme_header(&send_mme->header);
+ printf ("%u /***************************************************/\n",cyg_hal_sys_getpid());
+
+ switch(send_mme->header.un_mmtype.u32)
+ {
+ case DRV_STA_SET_MAC_ADDR_CNF :
+ case DRV_STA_SET_CCO_PREF_CNF :
+ case DRV_STA_SET_WAS_CCO_CNF :
+ case DRV_STA_SET_NPW_CNF :
+ case DRV_STA_SET_DPW_CNF :
+ case DRV_STA_SET_SL_CNF :
+ case DRV_STA_SET_M_STA_HFID_CNF :
+ case DRV_STA_SET_U_STA_HFID_CNF :
+ case DRV_STA_SET_AVLN_HFID_CNF :
+ case DRV_STA_SET_TONEMASK_CNF :
+ case DRV_STA_START_CNF :
+ case DRV_STA_STOP_CNF :
+ pld_maxlen = 2;
+ break;
+ default :
+ pld_maxlen = 0; /* TO DO : what length ? */
+ break;
+ }
+
+ printf ("%u /* MME PAYLOAD :\n",cyg_hal_sys_getpid());
+ switch(send_mme->header.un_mmtype.u32)
+ {
+ case DRV_STA_SET_MAC_ADDR_CNF :
+ case DRV_STA_SET_CCO_PREF_CNF :
+ case DRV_STA_SET_WAS_CCO_CNF :
+ case DRV_STA_SET_NPW_CNF :
+ case DRV_STA_SET_DPW_CNF :
+ case DRV_STA_SET_SL_CNF :
+ case DRV_STA_SET_M_STA_HFID_CNF :
+ case DRV_STA_SET_U_STA_HFID_CNF :
+ case DRV_STA_SET_AVLN_HFID_CNF :
+ case DRV_STA_SET_TONEMASK_CNF :
+ case DRV_STA_START_CNF :
+ case DRV_STA_STOP_CNF :
+ send_mme->result = cnf_result;
+ send_mme->errcode = cnf_errcode;
+ printf ("%u /*\t0x%08x : result ..... 0x%02X (%u) => %s\n",cyg_hal_sys_getpid(),(unsigned int)&send_mme->result,
+ send_mme->result,send_mme->result,get_str_drv_mme_cnf_result(send_mme->result));
+ printf ("%u /*\t0x%08x : errcode .... 0x%02X (%u)",cyg_hal_sys_getpid(),(unsigned int)&send_mme->errcode,
+ send_mme->errcode,send_mme->errcode);
+ if (send_mme->result != E_DRVMME_RESULT_SUCCESS)
+ printf (" => %s\n",get_str_drv_mme_cnf_errcode(send_mme->errcode));
+ else
+ printf ("\n");
+ break;
+ default :
+ printf("\n");
+ break;
+ }
+ printf ("%u /***************************************************/\n",cyg_hal_sys_getpid());
+
+ /* re-convert needed fields to big-endian... */
+ cpuhost_to_big_endian(&send_mme->header.un_osa.b[0],MAC_ADDR_SIZE);
+ cpuhost_to_big_endian(&send_mme->header.un_oda.b[0],MAC_ADDR_SIZE);
+ cpuhost_to_big_endian(&send_mme->header.un_vlan_tag.b[0],4);
+ cpuhost_to_big_endian(&send_mme->header.un_mtype.b[0],2);
+
+ /*
+ * take into account right mme header len depending on VLAN Tag field
+ * was present in incoming message or not (reply message header conforms
+ * to incoming message header)
+ */
+ if (!send_mme->header.vlan_tag_flag)
+ {
+ *cnf_len = (uint)MAX(60,MME_HEADER_MINSIZE+(int)pld_maxlen);
+ }
+ else
+ {
+ *cnf_len = (uint)MAX(60,MME_HEADER_MAXSIZE+(int)pld_maxlen);
+ }
+ memset(mme_tx_buffer,0x00,*cnf_len);
+
+#if 1
+ bitstream_init(&bstr_ctx,mme_tx_buffer,*cnf_len,BITSTREAM_WRITE);
+ bitstream_access(&bstr_ctx,&send_mme->header.un_osa.u64,48);
+ bitstream_access(&bstr_ctx,&send_mme->header.un_oda.u64,48);
+ if (send_mme->header.vlan_tag_flag) bitstream_access(&bstr_ctx,&send_mme->header.un_vlan_tag.u32,32);
+ bitstream_access(&bstr_ctx,&send_mme->header.un_mtype.u32,16);
+ bitstream_access(&bstr_ctx,&send_mme->header.un_mmv.u32,8);
+ bitstream_access(&bstr_ctx,&send_mme->header.un_mmtype.u32,16);
+ bitstream_access(&bstr_ctx,&send_mme->header.un_fmi.u32,16);
+ bitstream_access(&bstr_ctx,&send_mme->result,8);
+ bitstream_access(&bstr_ctx,&send_mme->errcode,8);
+ bitstream_finalise(&bstr_ctx);
+#endif
+
+ printf ("%u /***************************************************/\n",cyg_hal_sys_getpid());
+ printf ("%u /* STA : %d CP : SENDING AN MME (len = %u bytes)...\n",
+ cyg_hal_sys_getpid(),
+ 0/*cp_sta_global.mac_config->tei*/,
+ *cnf_len);
+#if 1
+ j = 0;
+ printf("%u /* ",cyg_hal_sys_getpid());
+ for (i = 0; i < (uint)(*cnf_len / 16); i++)
+ {
+ for (j = 0; j < 16; j++) printf ("%02x.",mme_tx_buffer[(i*16)+j]);
+ printf("\n");
+ printf("%u /* ",cyg_hal_sys_getpid());
+ }
+ for (i = 0; i < (*cnf_len % 16); i++)
+ {
+ printf ("%02x.",mme_tx_buffer[(j*16)+i]);
+ }
+ printf("\n");
+#endif
+ printf ("%u /***************************************************/\n",cyg_hal_sys_getpid());
+}