/**********************************************************
Prototype		void spi_app_receive_msg ( struct spi_os_msg * msg )
Type		function
Description	receive data from spi task message queue and
			Pack data for spi data.
			Then inqueue the message to spi_data_queue_XXX_tx
Param input	msg	: message received from other task
Return value	(none)
***********************************************************/
void spi_receive_msg_from_app(struct spi_os_msg *msg)
{
	enum SPI_MAIN_MSG_T type;
	enum SPI_DATA_QUEUE_TYPE_T q_type;
	enum SPI_DATA_TYPE_T mux_type;
	unsigned int in_length = 0, out_length = 0;
	void *in_buffer = 0;
	void *out_buffer = 0;

	type = msg->signal_code;
	in_length = msg->data_length;
	in_buffer = msg->data;

	switch (type) {
	case SPI_MAIN_MSG_IPC_SEND:
		q_type = SPI_DATA_QUEUE_TYPE_IPC_TX;
		mux_type = SPI_DATA_MUX_IPC;
		break;

	case SPI_MAIN_MSG_RAW_SEND:
		q_type = SPI_DATA_QUEUE_TYPE_RAW_TX;
		mux_type = SPI_DATA_MUX_RAW;
		break;

	case SPI_MAIN_MSG_RFS_SEND:
		q_type = SPI_DATA_QUEUE_TYPE_RFS_TX;
		mux_type = SPI_DATA_MUX_RFS;
		break;

	default:
		SPI_OS_ASSERT(("[SPI] spi_app_receive_msg Unknown type"));
		return;
	}

	out_buffer = spi_os_malloc(in_length+SPI_DATA_HEADER_SIZE);
	out_length = _pack_spi_data(mux_type, out_buffer, in_buffer, in_length);

	if (spi_data_inqueue(&spi_queue_info[q_type], out_buffer,
		out_length) == 0) {
		SPI_OS_ASSERT(("[SPI] spi_app_receive_msg inqueue[%d] Fail",
			q_type));
	}

	spi_os_free(in_buffer);
	spi_os_free(out_buffer);
}
int spi_data_parsing_rx_packet(void *buf, unsigned int length)
{
	struct spi_data_packet_header *spi_packet_header;
	char *spi_packet;
	unsigned int spi_packet_length;
	unsigned int spi_packet_cur_pos = SPI_DATA_PACKET_HEADER_SIZE;

	unsigned int spi_data_mux;
	unsigned int spi_data_length;
	char *spi_cur_data;

	struct spi_data_queue_info *queue_info;
	struct spi_data_div_buf *tx_div_buf;


	/* check spi packet header */
	if (*(unsigned int *)buf == 0x00000000
		|| *(unsigned int *)buf == 0xFFFFFFFF) {
		/* if spi header is invalid, */
		/* read spi header again with next 4 byte */
		buf += SPI_DATA_PACKET_HEADER_SIZE;
	}

	spi_packet = (char *) buf;

	/* read spi packet header */
	spi_packet_header = (struct spi_data_packet_header *) buf;
	spi_packet_length = SPI_DATA_PACKET_HEADER_SIZE +
		spi_packet_header->current_data_size;


	do {
		/* read spi data mux and set current queue */
		spi_os_memcpy(&spi_data_mux,
			spi_packet + spi_packet_cur_pos, SPI_DATA_MUX_SIZE);

		switch (spi_data_mux & SPI_DATA_MUX_NORMAL_MASK) {
		case SPI_DATA_MUX_IPC:
			queue_info =
			&spi_queue_info[SPI_DATA_QUEUE_TYPE_IPC_RX];
			tx_div_buf =
				&spi_div_buf[SPI_DATA_QUEUE_TYPE_IPC_RX];
			break;

		case SPI_DATA_MUX_RAW:
			queue_info =
				&spi_queue_info[SPI_DATA_QUEUE_TYPE_RAW_RX];
			tx_div_buf =
				&spi_div_buf[SPI_DATA_QUEUE_TYPE_RAW_RX];
			break;

		case SPI_DATA_MUX_RFS:
			queue_info =
				&spi_queue_info[SPI_DATA_QUEUE_TYPE_RFS_RX];
			tx_div_buf =
				&spi_div_buf[SPI_DATA_QUEUE_TYPE_RFS_RX];
			break;

		default:
			pr_err("%s len[%u], pos[%u]\n",
				"[SPI] ERROR : spi_data_parsing_rx_packet : MUX error",
				spi_packet_length, spi_packet_cur_pos);

			spi_os_trace_dump_low("mux error",
				spi_packet + spi_packet_cur_pos, 16);
			return spi_packet_cur_pos - SPI_DATA_PACKET_HEADER_SIZE;
		}

		/* read spi data length */
		spi_os_memcpy(&spi_data_length, spi_packet +
			spi_packet_cur_pos + SPI_DATA_LENGTH_OFFSET,
			SPI_DATA_LENGTH_SIZE);

		if (spi_data_mux & SPI_DATA_MUX_MORE_H
			|| spi_data_mux & SPI_DATA_MUX_MORE_M)
			spi_data_length += SPI_DATA_HEADER_SIZE_FRONT;
		else if (spi_data_mux & SPI_DATA_MUX_MORE_T)
			spi_data_length += SPI_DATA_HEADER_SIZE;
		else
			spi_data_length += SPI_DATA_HEADER_SIZE;

		/* read data and make spi data */
		spi_cur_data = spi_packet + spi_packet_cur_pos;

		/* verify spi data */
		if (_spi_data_verify(spi_cur_data, spi_data_mux) == 0) {
			spi_packet_cur_pos += spi_data_length;
			continue;
		}

		/* inqueue rx buffer */
		if (spi_data_mux & SPI_DATA_MUX_MORE_H
			|| spi_data_mux & SPI_DATA_MUX_MORE_M) {
			/* middle of divided packet. save to rx_div_buf */
			spi_os_memcpy((void *)(tx_div_buf->buffer +
				tx_div_buf->length),
				spi_cur_data, spi_data_length);
			tx_div_buf->length +=
				(spi_data_length - SPI_DATA_HEADER_SIZE_FRONT);
		} else if (spi_data_mux & SPI_DATA_MUX_MORE_T) {
			unsigned int spi_origine_len = 0;

			/* tail of divided packet. save to rx_div_buf */
			spi_os_memcpy((void *)(tx_div_buf->buffer +
				tx_div_buf->length),
				spi_cur_data, spi_data_length);
			tx_div_buf->length += spi_data_length;
			/* update spi data length at spi header */
			spi_origine_len =
				tx_div_buf->length - SPI_DATA_HEADER_SIZE;
			spi_os_memcpy(tx_div_buf->buffer +
				SPI_DATA_LENGTH_OFFSET,
				&(spi_origine_len), SPI_DATA_LENGTH_SIZE);

			/* inqueue from rx_div_buf */
			spi_data_inqueue(queue_info,
				tx_div_buf->buffer, tx_div_buf->length);

			spi_os_memset(tx_div_buf->buffer,
				0, SPI_DATA_DIVIDE_BUFFER_SIZE);
			tx_div_buf->length = 0;
		} else {
			/* normal packet */
			spi_data_inqueue(queue_info,
				spi_cur_data, spi_data_length);
		}

		/* move spi packet current posision */
		spi_packet_cur_pos += spi_data_length;
	} while ((spi_packet_length - 1) > spi_packet_cur_pos);

	return 1;
}