/**
 * @private
 * 
 * EO receive function.
 * 
 * Report various kinds of errors to demonstrate the EM error handling API.
 *
 */
static void
error_receive(void* eo_context, em_event_t event, em_event_type_t type, em_queue_t queue, void* q_ctx)
{
  error_event_t *error;
  em_queue_t     dest;
  eo_context_t  *eo_ctx = eo_context;


  error = em_event_pointer(event);

  dest        = error->dest;
  error->dest = queue;

  

  if(error->fatal)
  {
    printf("\nError log from %s [%u] on core %i!\n", eo_ctx->name, error->seq, em_core_id());
    
    em_free(event);
    
    /* Report a fatal error */
    em_error(EM_ERROR_SET_FATAL(0xdead), 0);
    
    return;
  }
  
  
  printf("Error log from %s [%u] on core %i!\n", eo_ctx->name, error->seq, em_core_id());

  /*       error   escope                 args  */
  em_error(0x1111, APPL_ESCOPE_OTHER);
  em_error(0x2222, APPL_ESCOPE_STR,       "Second error");
  em_error(0x3333, APPL_ESCOPE_STR_Q,     "Third  error", queue);
  em_error(0x4444, APPL_ESCOPE_STR_Q_SEQ, "Fourth error", queue, error->seq);

  /*
   * Example of an API call error - generates an EM API error
   */ 
  em_free(NULL);

  
  
  error->seq++;

  delay_spin(eo_ctx);

  em_send(event, dest);

  
  /* Request a fatal error to be generated every 8th event by 'EO C' */
  if((error->seq & 0x7) == 0x7)
  {
    // Send a new event to EO 'C' to cause a fatal error
    event = em_alloc(sizeof(error_event_t), EM_EVENT_TYPE_SW, EM_POOL_DEFAULT);

    error = em_event_pointer(event);

    error->dest  = 0; // don't care, never resent
    error->seq   = 0;
    error->fatal = 1;

    em_send(event, error_shm->queue_c);
  }

}
INT_32 
CWrapper::Initialize(const char * wrapperID)
{
		const char *ifname = "wlan0";
		char desc[NAMESIZE];
		INT_32 	ret = ERROR_RFTEST_GENERAL_ERROR;	

		assert(wrapperID);
		strcpy(m_wrapperID, wrapperID);
		
		if(!strcmp(m_wrapperID, "Local")||!strcmp(m_wrapperID, "local")||!strcmp(m_wrapperID, "LOCAL"))
			m_oid = new CLocalOID(ifname);
		else{
			em_error((char*)"CWrapper wrong wrapperID");
			goto out;
		}
		
		/*//added by MTK80758, CWrapperID now identifies CHIP ID MT5921 or MT6620
		if(strcmp(m_wrapperID, "MT5921"))
		{
			m_oid = new CLocalOID(ifname, "MT5921");
		}else if(strcmp(m_wrapperID, "MT6620"))
		{
			m_oid = new CLocalOID(ifname, "MT6620");
		}
		else
		{
			em_error("CWrapper wrong wrapperID");
			goto out;
		}
		*/	
		m_oid->GetChipID(ChipID, ifname);
		sprintf(desc, "%x", ChipID & DEVID_IDMSK);
		em_printf(MSG_DEBUG, (char*)"CWrapper name is %s desc is %s\n", ifname, desc);
		
		switch(ChipID & DEVID_IDMSK)
		{
#if 0
			case 0x5901:
			case 0x5911: 
				m_adapter= new CMT5911(name, desc, m_oid, this);
				break;
			
			case 5:
			case 0x5912:	
				m_adapter = new CMT5912(name, desc, m_oid, this);
				break;
	
			case 0x5905: 
				m_adapter = new CMT5905(name, desc, m_oid, this);
				break;
#endif			
			case 0x5921: 
				ChipID = 0x5921;
				em_printf(MSG_DEBUG, (char*)"Chip ID = 0x%x", ChipID);
				m_adapter = new CMT5921(ifname, desc, m_oid, CWrapper::getName());
				//ret = ERROR_RFTEST_SUCCESS;	
				ret = 0x5921;
				break;
			case 0x6620: 
				ChipID = 0x6620;
				em_printf(MSG_DEBUG, (char*)"Chip ID = 0x%x", ChipID);
				m_adapter = new CMT6620(ifname, desc, m_oid, CWrapper::getName());
				//ret = ERROR_RFTEST_SUCCESS;	
				ret = 0x6620;
				break;	
			default: 
				m_adapter = NULL;
				em_printf(MSG_ERROR, (char*)"Not supported Chip ID = 0x%x", ChipID);
				break;	 
	
		}

out:
		return ret;
}
/**
 * Init and startup of the Error Handler test application.
 *
 * @see main() and application_start() for setup and dispatch.
 */
void
test_init(appl_conf_t *const appl_conf)
{
  em_eo_t        eo;
  em_queue_t     queue;
  em_event_t     event;
  error_event_t* error;
  em_status_t    ret;  

  
  if(em_core_id() == 0) {
    error_shm = env_shared_reserve("ErrorSharedMem", sizeof(error_shm_t));
  }
  else {
    error_shm = env_shared_lookup("ErrorSharedMem");
  }
  

  if(error_shm == NULL) {
    em_error(EM_ERROR_SET_FATAL(0xec0de), APPL_ESCOPE_INIT, "Error init failed on EM-core: %u\n", em_core_id());
  }
    

  /*
   * Rest of the initializations only on one EM-core, return on all others.
   */  
  if(em_core_id() != 0)
  {
    return;
  }


  printf("\n**********************************************************************\n"
         "EM APPLICATION: '%s' initializing: \n"
         "  %s: %s() - EM-core:%i \n"
         "  Application running on %d EM-cores (procs:%d, threads:%d)."
         "\n**********************************************************************\n"
         "\n"
         ,
         appl_conf->name,
         NO_PATH(__FILE__), __func__,
         em_core_id(),
         em_core_count(),
         appl_conf->num_procs,
         appl_conf->num_threads);
         
  
  /* 
   * Register the application specifig global error handler
   * This replaces the EM internal default error hanlder
   */
  em_register_error_handler(global_error_handler); 


  /*
   * Create and start EO "A"
   */
  eo    = em_eo_create("EO A", error_start, NULL, error_stop, NULL, error_receive, &error_shm->eo_error_a);
  queue = em_queue_create("queue A", EM_QUEUE_TYPE_ATOMIC, EM_QUEUE_PRIO_NORMAL, EM_QUEUE_GROUP_DEFAULT);
  
  if((ret = em_eo_add_queue(eo, queue)) != EM_OK)
  {
    em_error(EM_ERROR_SET_FATAL(0xdead), APPL_ESCOPE_INIT,
             "EO or queue creation failed (%i). EO: %"PRI_EO", queue: %"PRI_QUEUE"\n",
             ret, eo, queue);
  }

  error_shm->queue_a = queue;

  if((ret = em_queue_enable(queue)) != EM_OK)
  {
    em_error(EM_ERROR_SET_FATAL(0xbeef), APPL_ESCOPE_INIT,
             "Queue A enable failed (%i). EO: %"PRI_EO", queue: %"PRI_QUEUE"\n",
             ret, eo, queue);
  }

  /*
   * Register an application 'EO A'-specific error handler
   */
  em_eo_register_error_handler(eo, eo_specific_error_handler); 
  em_eo_start(eo, NULL, 0, NULL);


  /*
   * Create and start EO "B"
   */
  eo    = em_eo_create("EO B", error_start, NULL, error_stop, NULL, error_receive, &error_shm->eo_error_b);
  queue = em_queue_create("queue B", EM_QUEUE_TYPE_ATOMIC, EM_QUEUE_PRIO_NORMAL, EM_QUEUE_GROUP_DEFAULT);

  if((ret = em_eo_add_queue(eo, queue)) != EM_OK)
  {
    em_error(EM_ERROR_SET_FATAL(0xacdc), APPL_ESCOPE_INIT,
             "EO or queue creation failed (%i). EO: %"PRI_EO", queue: %"PRI_QUEUE"\n",
             ret, eo, queue);
  }
  
  error_shm->queue_b = queue;
  
  if((ret = em_queue_enable(queue)) != EM_OK)
  {
    em_error(EM_ERROR_SET_FATAL(0xabba), APPL_ESCOPE_INIT,
             "Queue B enable failed (%i). EO: %"PRI_EO", queue: %"PRI_QUEUE"\n",
             ret, eo, queue);
  }
  
  /* Note: No 'EO B' specific error handler, use the application specific global error handler instead. */
  em_eo_start(eo, NULL, 0, NULL);


  /*
   * Create and start EO "C"
   */
  eo    = em_eo_create("EO C", error_start, NULL, error_stop, NULL, error_receive, &error_shm->eo_error_c);
  queue = em_queue_create("queue C", EM_QUEUE_TYPE_ATOMIC, EM_QUEUE_PRIO_NORMAL, EM_QUEUE_GROUP_DEFAULT);

  if((ret = em_eo_add_queue(eo, queue)) != EM_OK)
  {
    em_error(EM_ERROR_SET_FATAL(0xf00), APPL_ESCOPE_INIT,
             "EO or queue creation failed (%i). EO: %"PRI_EO", queue: %"PRI_QUEUE"\n",
             ret, eo, queue);
  }
  
  error_shm->queue_c = queue;

  if((ret = em_queue_enable(queue)) != EM_OK)
  {
    em_error(EM_ERROR_SET_FATAL(0xbad), APPL_ESCOPE_INIT,
             "Queue C enable failed (%i). EO: %"PRI_EO", queue: %"PRI_QUEUE"\n",
             ret, eo, queue);
  }

  /* Note: No 'EO C' specific error handler, use the application specific global error handler instead. */
  em_eo_start(eo, NULL, 0, NULL);
  
  
  
  
  /*
   * Send an event to EO A.
   * Store EO B's queue as the destination queue for EO A.
   */
  event = em_alloc(sizeof(error_event_t), EM_EVENT_TYPE_SW, EM_POOL_DEFAULT);

  error = em_event_pointer(event);

  error->dest  = error_shm->queue_b;
  error->seq   = 0;
  error->fatal = 0;

  em_send(event, error_shm->queue_a);


  /*
   * Send an event to EO C.
   * No dest queue stored since the fatal flag is set
   */
  event = em_alloc(sizeof(error_event_t), EM_EVENT_TYPE_SW, EM_POOL_DEFAULT);

  error = em_event_pointer(event);

  error->dest  = 0; // don't care, never resent
  error->seq   = 0;
  error->fatal = 1; // generate a fatal error when received

  em_send(event, error_shm->queue_c);
}