/* 回复确认信息或者核间函数调用结果返回 */
static s32 icc_send_test_001_cb1(u32 channel_id , u32 len, void* context)
{
	s32 confirm = ICC_RECV_OK;
	u8 *buf = NULL;

	buf = g_icc_test.channels[GET_CHN_ID(channel_id)].sub_channels[GET_FUNC_ID(channel_id)].rd_buf;
	if(!buf)
	{
		icc_print_error("malloc mem error!\n");
		return ICC_ERR;
	}

	icc_print_debug("channel_id:0x%x\n", channel_id);
	//icc_task_delay(20);
	icc_print_debug("confirm_sem:0x%x\n", &(g_icc_test.channels[GET_CHN_ID(channel_id)].sub_channels[GET_FUNC_ID(channel_id)-1].confirm_sem)); /*lint !e40 */

	if((s32)len == bsp_icc_read(channel_id, buf, len))
	{
		memcpy(&confirm, buf, sizeof(confirm));
		icc_print_debug("confirm:0x%x\n", confirm);
		if(ICC_RECV_OK == confirm)
		{
			g_icc_test.channels[GET_CHN_ID(channel_id)].sub_channels[GET_FUNC_ID(channel_id)-1].success_cnt++;
			osl_sem_up(&(g_icc_test.channels[GET_CHN_ID(channel_id)].sub_channels[GET_FUNC_ID(channel_id)-1].confirm_sem)); /*lint !e40 !e516 */
		}
	}

	return ICC_SEND_SYNC_RET;
}
/* 1. 比较发过来的信息是否是正确的(事先约定);
 * 2. 往对方核发确认信息,确认发过来的信息正确与否
 */
static s32 icc_send_test_001_cb0(u32 channel_id , u32 len, void* context)
{
	u32 i = 0;
	s32  confirm = ICC_RECV_OK;
	u32 start = (u32)context;
	u32 channel_idx = GET_CHN_ID(channel_id);
	u32 sub_chn_idx = GET_FUNC_ID(channel_id);

	icc_print_debug("====start:0x%x\n", start);
	
	if((s32)len != bsp_icc_read(channel_id, g_icc_test.channels[channel_idx].sub_channels[sub_chn_idx].rd_buf, len))
	{
		confirm = ICC_RECV_ERR;
		goto out;
	}

	for(i = 0; i < len; i++)
	{
		if(((u8)i + start) != g_icc_test.channels[channel_idx].sub_channels[sub_chn_idx].rd_buf[i])
		{
			confirm = ICC_RECV_ERR;
			goto out;
		}
	}

	confirm = ICC_RECV_OK;
	
out:
	channel_id = ((channel_idx << 16) | (sub_chn_idx + 1));
	bsp_icc_send(g_icc_dbg.send_cpu_id, channel_id, (u8 *)&confirm, sizeof(confirm));

	return ICC_OK;
	
}
/* 测试发送函数 */
static s32 icc_send_test(enum CPU_ID send_cpu_id, u32 channel_id, u8 *buf, u32 data_len, u32 start, u32 timeout)
{
	u32 i = 0;

	for(i = 0; i < data_len; i++)
	{
		buf[i]= (u8)(i + start);
	}

	icc_print_debug("enter: channel_id=0x%x\n", channel_id);

	if((s32)data_len != bsp_icc_send(send_cpu_id, channel_id, buf, data_len))
	{
		icc_print_error("bsp_icc_send error\n");
		return ICC_ERR;
	}

	if(osl_sem_downtimeout(&(g_icc_test.channels[GET_CHN_ID(channel_id)].sub_channels[GET_FUNC_ID(channel_id)].confirm_sem), (long)timeout)) /*lint !e732 */
	{
		icc_print_error("icc_sem_take error\n");
		return ICC_ERR;
	}

	return ICC_OK;
}
/* 收对方核回过来的确认信息: 如果信息是ICC_CONF_MSG_TYPE1 */
s32 icc_send_test_cb1_new(u32 channel_id , u32 len, void* context)
{
	u8  confirm = (u8)ICC_RECV_OK;
	u32 channel_idx = GET_CHN_ID(channel_id);
	u32 sub_chn_idx = GET_FUNC_ID(channel_id);
	s32 read_len = sizeof(confirm);

	icc_print_debug("enter\n");

	if(read_len == bsp_icc_read(channel_id, &confirm, len))
	{
		icc_print_debug("confirm:0x%x\n", confirm);
		if(ICC_CONF_MSG_TYPE1 == confirm)
		{
			g_icc_test.channels[channel_idx].sub_channels[sub_chn_idx-1].success_cnt++;
			osl_sem_up(&(g_icc_test.channels[channel_idx].sub_channels[sub_chn_idx-1].confirm_sem)); /*lint !e40 !e516 */
		}
		else if(ICC_CONF_MSG_TYPE2 == confirm)
		{
			g_icc_test.channels[channel_idx].sub_channels[sub_chn_idx+1].success_cnt++;
			osl_sem_up(&(g_icc_test.channels[channel_idx].sub_channels[sub_chn_idx+1].confirm_sem)); /*lint !e40 !e516 */
		}
		else
		{
			icc_print_error("error: wrong confirm:0x%x\n", confirm);
		}
	}
	else
	{
		icc_print_error("icc read error\n", confirm);
	}

	return ICC_OK;
}
static s32 icc_test_multi_send_func(void *obj)
{
	u32 channel_id = (u32)obj;
	u32 i = 0;
	u8 *buf = g_icc_test.channels[GET_CHN_ID(channel_id)].sub_channels[GET_FUNC_ID(channel_id)].wr_buf;

	for(i = 0; i < ICC_TEST_SEND_CNT; i++)
	{
		icc_task_delay(200);
		icc_print_debug("try to send channel%d's data, buf: 0x%x", channel_id, buf);
		if(ICC_OK != icc_send_test(ICC_SEND_CPU, channel_id, buf, 30, GET_FUNC_ID(channel_id), ICC_TAKE_SEM_TIMEOUT_JIFFIES))
		{
			icc_print_info("[FAIL] asynchronous send\n");
			return ICC_TEST_FAIL;
		}
	}

	icc_print_info("[PASS] asynchronous send\n");

	return ICC_TEST_PASS;
}
/* 该回调用于接收核不读数据,直接回确认信息给发送核 */
s32 icc_send_test_cb0_new(u32 channel_id , u32 len, void* context)
{
	u8  confirm     = ICC_CONF_MSG_TYPE1;
	u32 channel_idx = GET_CHN_ID(channel_id);
	u32 sub_chn_idx = GET_FUNC_ID(channel_id);
	u32 send_len    = sizeof(confirm);

	icc_print_debug("enter: channel_id=0x%x\n", ((channel_idx << 16) | (sub_chn_idx + 1)));

	if((s32)send_len != bsp_icc_send(g_icc_dbg.send_cpu_id, ((channel_idx << 16) | (sub_chn_idx + 1)), &confirm, send_len))
	{
		icc_print_error("send error!\n");
	}

	return ICC_OK;
}
/* 任务处理函数,读取通道里的数据 */
s32 icc_read_task_entry(void *obj)
{
	u32 channel_id  = (u32)obj;
	u32 channel_idx = GET_CHN_ID(channel_id);
	u32 sub_chn_idx = GET_FUNC_ID(channel_id);
	s32 read_len    = 0;
	u32 start       = 0;
	u8  confirm     = (u8)ICC_RECV_OK;
	s32 i           = 0;
	u8 buf[ICC_NEW_DATA_LEN]    = {0};

	icc_print_debug("enter!!!");

	for(;g_icc_test.recv_task_flag;)
	{
		osl_sem_down(&g_icc_test.recv_task_sem);

		read_len = bsp_icc_read(channel_id, buf, ICC_NEW_DATA_LEN);
		if(read_len < 0 || read_len > ICC_NEW_DATA_LEN)
		{
			confirm = (u8)ICC_RECV_ERR;
		}
		else
		{
			for(i = 0; i < read_len; i++)
			{
				if(((u8)i + start) != buf[i])
				{
					confirm = (u8)ICC_RECV_ERR;
				}
			}
			confirm = ICC_CONF_MSG_TYPE2;
		}

		icc_print_debug("channel_id=0x%x, confirm=0x%x\n", channel_id, confirm);
		bsp_icc_send(g_icc_dbg.send_cpu_id, (channel_idx << 16) | (sub_chn_idx - 1), &confirm, sizeof(confirm));
	}

	return 0;
}
static s32 icc_test_multi_send_test_init(u32 sn, u32 channel_id, task_entry entry)
{
	u32 channel_idx = GET_CHN_ID(channel_id);
	u32 sub_chn_idx = GET_FUNC_ID(channel_id);
	s32 *task_id = NULL;
	u8 name[30] = {0};
	
	icc_print_debug("************entry");

	g_icc_test.channels[channel_idx].sub_channels[sub_chn_idx].success_cnt = 0;
	icc_print_debug("i:0x%x, channel_id:0x%x", sn, channel_id);
		
	task_id = &(g_icc_test.channels[channel_idx].sub_channels[sub_chn_idx].task_id);
	sprintf((char*)name, "icc_mul%d", channel_id);

#if defined(__KERNEL__) || defined(__VXWORKS__)
	if(ICC_ERR == osl_task_init((char *)name, ICC_TEST_TASK_PRI, ICC_TASK_STK_SIZE,
		(task_entry)entry, (void*)(channel_id), (u32 *)task_id))
    {
        icc_print_error("create send test task error\n");
        return ICC_ERR;
    }
#elif defined(__CMSIS_RTOS)
	*task_id = osThreadCreate(osThread(icc_test_multi_send_func), (void*)channel_id);
	if(NULL == *task_id)
	{
		icc_print_error("create icc_wait task error\n");
		return ICC_ERR;
	}
#endif
	
	icc_print_debug("create send test task successfully\n");

	return ICC_OK;

}
static s32 icc_test_multi_send_sync_func(void *obj)
{
	u32 channel_id = (u32)obj;
	u32 channel_idx = GET_CHN_ID(channel_id);
	u32 sub_chn_idx = GET_FUNC_ID(channel_id);
	u32 i = 0;
	u32 send_data = 0x10305070;

#ifdef ICC_HAS_SYNC_SEND_FEATURE
	for(i = 0; i < ICC_TEST_SEND_CNT; i++)
	{
		if (ICC_SEND_SYNC_RET != bsp_icc_send_sync(ICC_SEND_CPU,channel_id,(u8*)&send_data,sizeof(send_data),MAX_SCHEDULE_TIMEOUT)) /*lint !e40 !e516*/
		{
			icc_print_error("[FAIL] synchronous send!\n");
			return ICC_TEST_PASS;
		}
		g_icc_test.channels[channel_idx].sub_channels[sub_chn_idx].success_cnt++;
	}
#endif

	icc_print_info("[PASS] synchronous send\n");

	return ICC_TEST_PASS;
}
int icc_channel_packet_dump(struct icc_channel_packet *packet)
{
	struct icc_channel *channel = NULL;
	const char *name = NULL;
	struct icc_channel_vector *vector = NULL;
	read_cb_func read_cb = NULL;
	void *read_context = NULL;
	int ret = ICC_OK;

	if (GET_CHN_ID(packet->channel_id) >= ICC_CHN_ID_MAX)
	{
		ret  = ICC_ERR;
		name = "unknown";
		goto packet_dump; /*lint !e801 */
	}

	channel = g_icc_ctrl.channels[GET_CHN_ID(packet->channel_id)];
	if (NULL == channel)
	{
		ret  = ICC_ERR;
		name = "unknown";
		goto packet_dump; /*lint !e801 */
	}

	name = channel->name;
	if (GET_FUNC_ID(packet->channel_id) >= channel->func_size)
	{
		ret  = ICC_ERR;
		goto packet_dump; /*lint !e801 */
	}
	vector = &channel->rector[GET_FUNC_ID(packet->channel_id)];
	read_cb = vector->read_cb;
	read_context = vector->read_context;

	if ((0 == g_icc_dbg.msg_print_sw) && (0 == g_icc_ctrl.wake_up_flag) && (0 == g_icc_ctrl.sleep_flag))
	{
		return ret;
	}

	if (1 == g_icc_ctrl.wake_up_flag)
	{
		g_icc_ctrl.wake_up_flag = 0;
		icc_print_info("[C SR]icc recv msg dump\n");
	}

	if (1 == g_icc_ctrl.sleep_flag)
	{
		g_icc_ctrl.sleep_flag = 0;
	}

packet_dump:
	icc_pm_om_log(packet, read_cb, read_context);
	icc_print_info("*******************icc[%s]*******************\n", name);
	icc_print_info("channel_id  : 0x%x\n", packet->channel_id);
	icc_print_info("len         : 0x%x\n", packet->len);
	icc_print_info("src_cpu_id  : 0x%x\n", packet->src_cpu_id);
	icc_print_info("timestamp   : 0x%x\n", packet->timestamp);
	icc_print_info("task_id     : 0x%x\n", packet->task_id);
	icc_print_info("read_cb     : 0x%p\n", read_cb);
	icc_print_info("read_context: 0x%p\n", read_context);
	icc_print_info("**********************************************\n");
	return ret;
}