STATUS process_jtag_message()

in common/recipes-core/asd/files/daemon/socket_main.c [724:1005]


STATUS process_jtag_message(struct spi_message *s_message) {
    int response_cnt = 0;
    JtagStates end_state;
    STATUS status = ST_OK;
    int size = get_message_size(s_message);
    struct packet_data packet;
    unsigned char *data_ptr;
    uint8_t cmd;

    if (size == -1) {
        ASD_log(LogType_Error, "Failed to process jtag message because "
               "get message size failed.");
        return ST_ERR;
    }

    memset(&out_msg.header, 0, sizeof(struct message_header));
    memset(out_msg.buffer, 0, MAX_DATA_SIZE);

    ASD_log(LogType_JTAG, "NetReq tag: %d size: %d", s_message->header.tag, size);
    ASD_log_buffer(LogType_JTAG, s_message->buffer, size, "NetReq");

    packet.next_data = s_message->buffer;
    packet.used = 0;
    packet.available = size;

    while (packet.used < packet.available) {
        data_ptr = get_packet_data(&packet, 1);
        if (data_ptr == NULL) {
            ASD_log(LogType_Error, "no command to read, short packet");
            status = ST_ERR;
            break;
        }

        cmd = *data_ptr;
        if (cmd == WRITE_EVENT_CONFIG) {
            data_ptr = get_packet_data(&packet, 1);
            if (data_ptr == NULL) {
                ASD_log(LogType_Error, "Failed to read data for WRITE_EVENT_CONFIG, short packet");
                status = ST_ERR;
                break;
            }

            status = write_event_config(*data_ptr);
            if(status != ST_OK) {
                ASD_log(LogType_Error, "write_event_config failed, %d", status);
                break;
            }
        } else if (cmd >= WRITE_CFG_MIN && cmd <= WRITE_CFG_MAX) {
            status = write_cfg((writeCfg)cmd, &packet);
            if(status != ST_OK) {
                ASD_log(LogType_Error, "write_cfg failed, %d", status);
                break;
            }
        } else if (cmd == WRITE_PINS) {
            data_ptr = get_packet_data(&packet, 1);
            if (data_ptr == NULL) {
                ASD_log(LogType_Error, "Failed to read data for WRITE_PINS, short packet");
                status = ST_ERR;
                break;
            }

            uint8_t data = *data_ptr;
            bool assert = (data >> 7) == 1;
            Pin pin = PIN_MIN;
            uint8_t index = data & WRITE_PIN_MASK;

            if (index > PIN_MIN && index < PIN_MAX) {
                pin = (Pin)index;
                status = target_write(target_control_handle, pin, assert);
                if(status != ST_OK) {
                    ASD_log(LogType_Error, "target_write failed, %d", status);
                    break;
                }
            } else if ((index & SCAN_CHAIN_SELECT) == SCAN_CHAIN_SELECT) {
                uint8_t scan_chain = (index & SCAN_CHAIN_SELECT_MASK);
                if (scan_chain >= MAX_SCAN_CHAINS) {
                    ASD_log(LogType_Error, "Unexpected scan chain: 0x%02x", scan_chain);
                    status = ST_ERR;
                    break;
                }
                status = target_jtag_chain_select(target_control_handle, (scanChain)scan_chain);
                if(status != ST_OK) {
                    ASD_log(LogType_Error, "target_jtag_chain_select failed, %d", status);
                    break;
                }
                status = JTAG_set_active_chain(jtag_handler, (scanChain)scan_chain);
                if(status != ST_OK) {
                    ASD_log(LogType_Error, "JTAG_set_active_chain failed, %d", status);
                    break;
                }
            } else {
                ASD_log(LogType_Error, "Unexpected WRITE_PINS index: 0x%02x", index);
                status = ST_ERR;
                break;
            }
        } else if (cmd >= READ_STATUS_MIN && cmd <= READ_STATUS_MAX) {
            int bytes_written = 0;
            ReadType readStatusTypeIndex;
            uint8_t index = (cmd & READ_STATUS_MASK);
            if (index > READ_TYPE_MIN && index < READ_TYPE_MAX)
                readStatusTypeIndex = (ReadType)index;
            else {
                ASD_log(LogType_Error,  "Unexpected READ_STATUS index: 0x%02x", index);
                status = ST_ERR;
                break;
            }

            data_ptr = get_packet_data(&packet, 1);
            if (data_ptr == NULL) {
                ASD_log(LogType_Error, "Failed to read data for Read Status, short packet");
                status = ST_ERR;
                break;
            }

            if (response_cnt+2 > MAX_DATA_SIZE) {
                ASD_log(LogType_Error, "Failed to process READ_STATUS. "
                        "Response buffer already full");
                status = ST_ERR;
                break;
            }

            uint8_t pin = (*data_ptr & READ_STATUS_PIN_MASK);
            status = read_status(readStatusTypeIndex, pin, &out_msg.buffer[response_cnt],
                                 MAX_DATA_SIZE-response_cnt, &bytes_written);
            if(status != ST_OK) {
                ASD_log(LogType_Error, "read_status failed, %d", status);
                break;
            }
            response_cnt += bytes_written;
        } else if (cmd == WAIT_CYCLES_TCK_DISABLE ||
                   cmd == WAIT_CYCLES_TCK_ENABLE) {

            data_ptr = get_packet_data(&packet, 1);
            if (data_ptr == NULL) {
                ASD_log(LogType_Error, "Failed to read data for WAIT_CYCLES_TCK, short packet");
                status = ST_ERR;
                break;
            }

            unsigned int number_of_cycles = *data_ptr;
            if (number_of_cycles==0)
                number_of_cycles = 256;

            ASD_log(LogType_Debug, "Wait cycle of %d", number_of_cycles);
            status = JTAG_wait_cycles(jtag_handler, number_of_cycles);
            if(status != ST_OK) {
                ASD_log(LogType_Error, "JTAG_wait_cycles failed, %d", status);
                break;
            }
        } else if (cmd == WAIT_PRDY) {
            status = target_wait_PRDY(target_control_handle, prdy_timeout);
            if(status != ST_OK) {
                ASD_log(LogType_Error, "target_wait_PRDY failed, %d", status);
                break;
            }
        } else if (cmd == CLEAR_TIMEOUT) {
            // Command not yet implemented. This command does not apply to JTAG
            // so we will likely not implement it.
            ASD_log(LogType_Debug, "Clear Timeout command not yet implemented");
        } else if (cmd == TAP_RESET) {
            status = JTAG_tap_reset(jtag_handler);
            if(status != ST_OK) {
                ASD_log(LogType_Error, "JTAG_tap_reset failed, %d", status);
                break;
            }
        } else if (cmd >= TAP_STATE_MIN && cmd <= TAP_STATE_MAX) {
            status = JTAG_set_tap_state(jtag_handler, (JtagStates)(cmd & TAP_STATE_MASK));
            if(status != ST_OK) {
                ASD_log(LogType_Error, "JTAG_set_tap_state failed, %d", status);
                break;
            }
        } else if (cmd >= WRITE_SCAN_MIN && cmd <= WRITE_SCAN_MAX) {
            uint8_t num_of_bits = 0;
            uint8_t num_of_bytes = 0;

            get_scan_length(cmd, &num_of_bits, &num_of_bytes);
            data_ptr = get_packet_data(&packet, num_of_bytes);
            if (data_ptr == NULL) {
                ASD_log(LogType_Error, "Failed to read data from buffer: %d", num_of_bytes);
                status = ST_ERR;
                break;
            }

            status = determine_shift_end_state(ScanType_Write, &packet, &end_state);
            if(status != ST_OK) {
                ASD_log(LogType_Error, "determine_shift_end_state failed, %d", status);
                break;
            }
            status = JTAG_shift(jtag_handler, num_of_bits,
                                MAX_DATA_SIZE - packet.used - num_of_bytes,
                                data_ptr, 0, NULL, end_state);
            if(status != ST_OK) {
                ASD_log(LogType_Error, "JTAG_shift failed, %d", status);
                break;
            }
        } else if (cmd >= READ_SCAN_MIN && cmd <= READ_SCAN_MAX) {
            uint8_t num_of_bits = 0;
            uint8_t num_of_bytes = 0;

            get_scan_length(cmd, &num_of_bits, &num_of_bytes);
            if (response_cnt+sizeof(char)+num_of_bytes > MAX_DATA_SIZE) {
                ASD_log(LogType_Error, "Failed to process READ_SCAN. "
                        "Response buffer already full");
                status = ST_ERR;
                break;
            }
            out_msg.buffer[response_cnt++] = cmd;
            status = determine_shift_end_state(ScanType_Read, &packet, &end_state);
            if(status != ST_OK) {
                ASD_log(LogType_Error, "determine_shift_end_state failed, %d", status);
                break;
            }
            status = JTAG_shift(jtag_handler, num_of_bits, 0, NULL,
                                MAX_DATA_SIZE-response_cnt,
                                (unsigned char*)&(out_msg.buffer[response_cnt]),
                                end_state);
            if(status != ST_OK) {
                ASD_log(LogType_Error, "JTAG_shift failed, %d", status);
                break;
            }
            response_cnt += num_of_bytes;
        } else if (cmd >= READ_WRITE_SCAN_MIN && cmd <= READ_WRITE_SCAN_MAX) {
            uint8_t num_of_bits = 0;
            uint8_t num_of_bytes = 0;
            get_scan_length(cmd, &num_of_bits, &num_of_bytes);
            if (response_cnt+sizeof(char)+num_of_bytes > MAX_DATA_SIZE) {
                ASD_log(LogType_Error, "Failed to process READ_WRITE_SCAN. "
                        "Response buffer already full");
                status = ST_ERR;
                break;
            }
            out_msg.buffer[response_cnt++] = cmd;
            data_ptr = get_packet_data(&packet, num_of_bytes);
            if (data_ptr == NULL) {
                ASD_log(LogType_Error, "Failed to read data from buffer: %d", num_of_bytes);
                status = ST_ERR;
                break;
            }
            status = determine_shift_end_state(ScanType_ReadWrite, &packet, &end_state);
            if(status != ST_OK) {
                ASD_log(LogType_Error, "determine_shift_end_state failed, %d", status);
                break;
            }
            status = JTAG_shift(jtag_handler, num_of_bits,
                                MAX_DATA_SIZE - packet.used + num_of_bytes + 1,
                                data_ptr, MAX_DATA_SIZE-response_cnt,
                                (unsigned char*)&(out_msg.buffer[response_cnt]),
                                end_state);
            if(status != ST_OK) {
                ASD_log(LogType_Error, "JTAG_shift failed, %d", status);
                break;
            }
            response_cnt += num_of_bytes;
        } else {
            // Unknown Command
            ASD_log(LogType_Error, "Encountered unknown command 0x%02x", (int)cmd);
            status = ST_ERR;
            break;
        }
    }

    if (status == ST_OK) {
        memcpy(&out_msg.header, &s_message->header, sizeof(struct message_header));

        out_msg.header.size_lsb = response_cnt & 0xFF;
        out_msg.header.size_msb = (response_cnt >> 8) & 0x1F;
        out_msg.header.cmd_stat = ASD_SUCCESS;

        status = send_out_msg_on_socket(&out_msg);
        if (status != ST_OK) {
            ASD_log(LogType_Error | LogType_NoRemote, "Failed to send message back on the socket");
        }
    } else {
        // Send error code to client
        extnet_conn_t authd_conn;
        if (session_get_authenticated_conn(&authd_conn) != ST_OK) {
            send_error_message(&authd_conn, s_message, ASD_UNKNOWN_ERROR);
        }
    }

    return status;
}