fm_s32 fm_event_parser(fm_s32(*rds_parser)(struct rds_rx_t*, fm_s32))
{
    fm_u16 tmp_reg;

    fm_ctrl_rx(FM_MAIN_INTR, &tmp_reg);

    if (tmp_reg&FM_INTR_STC_DONE) {
        //clear status flag
        fm_ctrl_tx(FM_MAIN_INTR, tmp_reg | FM_INTR_STC_DONE);
        FM_EVENT_SEND(link_event->ln_event, FLAG_TEST);
    }

    if (tmp_reg&FM_INTR_RDS) {
        //clear status flag
        fm_ctrl_tx(FM_MAIN_INTR, tmp_reg | FM_INTR_RDS);

        /*Handle the RDS data that we get*/
        if (rds_parser) {
            rds_parser(NULL, 0); //mt6626 rds lib will get rds raw data by itself
        } else {
            WCN_DBG(FM_WAR | LINK, "no method to parse RDS data\n");
        }
    }

    return 0;
}
Пример #2
0
fm_s32 fm_event_parser(fm_s32(*rds_parser) (struct rds_rx_t *, fm_s32))
{
	fm_s32 len;
	fm_s32 i = 0;
	fm_u8 opcode = 0;
	fm_u16 length = 0;
	fm_u8 ch;
	fm_u8 rx_buf[RX_BUF_SIZE + 10] = { 0 };	/* the 10 bytes are protect gaps */
	static volatile fm_task_parser_state state = FM_TASK_RX_PARSER_PKT_TYPE;
	struct fm_trace_t trace;
	struct task_struct *task = current;

	len = mtk_wcn_stp_receive_data(rx_buf, RX_BUF_SIZE, FM_TASK_INDX);
	WCN_DBG(FM_DBG | LINK, "[len=%d],[CMD=0x%02x 0x%02x 0x%02x 0x%02x]\n", len, rx_buf[0],
		rx_buf[1], rx_buf[2], rx_buf[3]);

	while (i < len) {
		ch = rx_buf[i];

		switch (state) {
		case FM_TASK_RX_PARSER_PKT_TYPE:

			if (ch == FM_TASK_EVENT_PKT_TYPE) {
				if ((i + 5) < RX_BUF_SIZE) {
					WCN_DBG(FM_DBG | LINK,
						"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
						rx_buf[i], rx_buf[i + 1], rx_buf[i + 2],
						rx_buf[i + 3], rx_buf[i + 4], rx_buf[i + 5]);
				} else {
					WCN_DBG(FM_DBG | LINK, "0x%02x 0x%02x\n", rx_buf[i],
						rx_buf[i + 1]);
				}

				state = FM_TASK_RX_PARSER_OPCODE;
			} else {
				WCN_DBG(FM_ALT | LINK,
					"event pkt type error (rx_buf[%d] = 0x%02x)\n", i, ch);
			}

			i++;
			break;

		case FM_TASK_RX_PARSER_OPCODE:
			i++;
			opcode = ch;
			state = FM_TASK_RX_PARSER_PKT_LEN_1;
			break;

		case FM_TASK_RX_PARSER_PKT_LEN_1:
			i++;
			length = ch;
			state = FM_TASK_RX_PARSER_PKT_LEN_2;
			break;

		case FM_TASK_RX_PARSER_PKT_LEN_2:
			i++;
			length |= (fm_u16) (ch << 0x8);

#ifdef FM_TRACE_ENABLE
			trace.type = FM_TASK_EVENT_PKT_TYPE;
			trace.opcode = opcode;
			trace.len = length;
			trace.tid = (fm_s32) task->pid;
			fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
			fm_memcpy(trace.pkt, &rx_buf[i],
				  (length > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : length);

			if (fm_true == FM_TRACE_FULL(cmd_fifo)) {
				FM_TRACE_OUT(cmd_fifo, NULL);
			}
			FM_TRACE_IN(cmd_fifo, &trace);
#endif
			if (length > 0) {
				state = FM_TASK_RX_PARSER_PKT_PAYLOAD;
			} else if (opcode == CSPI_WRITE_OPCODE) {
				state = FM_TASK_RX_PARSER_PKT_TYPE;
				FM_EVENT_SEND(link_event->ln_event, FLAG_CSPI_WRITE);
			} else {
				state = FM_TASK_RX_PARSER_PKT_TYPE;
				FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
			}

			break;

		case FM_TASK_RX_PARSER_PKT_PAYLOAD:

			switch (opcode) {
			case FM_TUNE_OPCODE:

				if ((length == 1) && (rx_buf[i] == 1)) {
					FM_EVENT_SEND(link_event->ln_event, FLAG_TUNE_DONE);
				}

				break;

			case FM_SOFT_MUTE_TUNE_OPCODE:

				if (length >= 2) {
					fm_memcpy(link_event->result.cqi, &rx_buf[i],
						  (length >
						   FM_CQI_BUF_SIZE) ? FM_CQI_BUF_SIZE : length);
					FM_EVENT_SEND(link_event->ln_event, FLAG_SM_TUNE);
				}
				break;

			case FM_SEEK_OPCODE:

				if ((i + 1) < RX_BUF_SIZE) {
					link_event->result.seek_result = rx_buf[i] + (rx_buf[i + 1] << 8);	/* 8760 means 87.60Mhz */
				}

				FM_EVENT_SEND(link_event->ln_event, FLAG_SEEK_DONE);
				break;

			case FM_SCAN_OPCODE:

				/* check if the result data is long enough */
				if ((RX_BUF_SIZE - i) < (sizeof(fm_u16) * FM_SCANTBL_SIZE)) {
					WCN_DBG(FM_ALT | LINK,
						"FM_SCAN_OPCODE err, [tblsize=%d],[bufsize=%d]\n",
						(unsigned int)(sizeof(fm_u16) * FM_SCANTBL_SIZE),
						(unsigned int)(RX_BUF_SIZE - i));
					FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE);
					return 0;
				} else if ((length >= FM_CQI_BUF_SIZE)
					   && ((RX_BUF_SIZE - i) >= FM_CQI_BUF_SIZE)) {
					fm_memcpy(link_event->result.cqi, &rx_buf[i],
						  FM_CQI_BUF_SIZE);
					FM_EVENT_SEND(link_event->ln_event, FLAG_CQI_DONE);
				} else {
					fm_memcpy(link_event->result.scan_result, &rx_buf[i],
						  sizeof(fm_u16) * FM_SCANTBL_SIZE);
					FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE);
				}

				break;

			case FSPI_READ_OPCODE:

				if ((i + 1) < RX_BUF_SIZE) {
					link_event->result.fspi_rd =
					    (rx_buf[i] + (rx_buf[i + 1] << 8));
				}

				FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
				break;
			case CSPI_READ_OPCODE:
				{
					if ((i + 1) < RX_BUF_SIZE) {
						link_event->result.cspi_rd =
						    (rx_buf[i] + (rx_buf[i + 1] << 8) +
						     (rx_buf[i + 2] << 16) + (rx_buf[i + 3] << 24));
					}

					FM_EVENT_SEND(link_event->ln_event, FLAG_CSPI_READ);
					break;
				}
			case FM_HOST_READ_OPCODE:
				{
					if ((i + 1) < RX_BUF_SIZE) {
						link_event->result.cspi_rd =
						    (rx_buf[i] + (rx_buf[i + 1] << 8) +
						     (rx_buf[i + 2] << 16) + (rx_buf[i + 3] << 24));
					}

					FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
					break;
				}

			case RDS_RX_DATA_OPCODE:

				/* check if the rds data is long enough */
				if ((RX_BUF_SIZE - i) < length) {
					WCN_DBG(FM_ALT | LINK,
						"RDS RX err, [rxlen=%d],[bufsize=%d]\n",
						(fm_s32) length, (RX_BUF_SIZE - i));
					FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
					break;
				}
				/* copy rds data to rds buf */
				fm_memcpy(&link_event->result.rds_rx_result, &rx_buf[i], length);

				/*Handle the RDS data that we get */
				if (rds_parser) {
					rds_parser(&link_event->result.rds_rx_result, length);
				} else {
					WCN_DBG(FM_WAR | LINK, "no method to parse RDS data\n");
				}

				FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
				break;

			default:
				FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
				break;
			}

			state = FM_TASK_RX_PARSER_PKT_TYPE;
			i += length;
			break;

		default:
			break;
		}
	}

	return 0;
}