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; }
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; }