STATUS process_i2c_messages()

in common/recipes-core/asd_1.4.3/files/daemon/asd_msg.c [2095:2274]


STATUS process_i2c_messages(ASD_MSG* state, struct asd_message* in_msg)
{
    int response_cnt = 0;
    STATUS status;
    int size;
    struct packet_data packet;
    uint8_t* data_ptr;
    uint8_t cmd;
    bool i2c_command_pending = false;
    bool force_stop = false;

    if (!state || !in_msg)
    {
        ASD_log(ASD_LogLevel_Error, ASD_LogStream_I2C, ASD_LogOption_None,
                "Invalid process_i2c_messages input.");
        return ST_ERR;
    }

    I2C_Msg_Builder* builder = I2CMsgBuilder();

    if (!builder)
    {
        ASD_log(ASD_LogLevel_Error, ASD_LogStream_I2C, ASD_LogOption_None,
                "Invalid process_i2c_messages input.");
        status = ST_ERR;
    }
    else
    {
        size = get_message_size(in_msg);
        if (size == -1)
        {
            ASD_log(ASD_LogLevel_Error, ASD_LogStream_I2C, ASD_LogOption_None,
                    "Failed to process i2c message because "
                    "get message size failed.");
            status = ST_ERR;
        }
        else
        {

            memset(&state->out_msg.header, 0, sizeof(struct message_header));
            memset(&state->out_msg.buffer, 0, MAX_DATA_SIZE);
            if (memcpy_safe(&state->out_msg.header,
                            sizeof(struct message_header), &in_msg->header,
                            sizeof(struct message_header)))
            {
                ASD_log(ASD_LogLevel_Error, ASD_LogStream_JTAG,
                        ASD_LogOption_None, "memcpy_safe: message header to \
							out msg header copy failed.");
            }
            status = i2c_msg_initialize(builder);
            if (status != ST_OK)
            {
                ASD_log(ASD_LogLevel_Error, ASD_LogStream_I2C,
                        ASD_LogOption_None,
                        "Failed to initialize i2c msg builder.");
            }
            else
            {
#ifdef ENABLE_DEBUG_LOGGING
                ASD_log(ASD_LogLevel_Debug, ASD_LogStream_I2C,
                        ASD_LogOption_None, "NetReq tag: %d size: %d",
                        in_msg->header.tag, size);
                ASD_log_buffer(ASD_LogLevel_Debug, ASD_LogStream_I2C,
                               ASD_LogOption_None, in_msg->buffer, (size_t)size,
                               "NetReq");
#endif
                packet.next_data = in_msg->buffer;
                packet.used = 0;
                packet.total = size;

                while (packet.used < packet.total)
                {
                    data_ptr = get_packet_data(&packet, 1);

                    cmd = *data_ptr;
                    if (cmd == I2C_WRITE_CFG_BUS_SELECT)
                    {
                        status =
                            do_bus_select_command(state->i2c_handler, &packet);
                    }
                    else if (cmd == I2C_WRITE_CFG_SCLK)
                    {
                        status =
                            do_set_sclk_command(state->i2c_handler, &packet);
                    }
                    else if (cmd >= I2C_READ_MIN && cmd <= I2C_READ_MAX)
                    {
                        status =
                            do_read_command(cmd, builder, &packet, &force_stop);
                        i2c_command_pending = true;
                    }
                    else if (cmd >= I2C_WRITE_MIN && cmd <= I2C_WRITE_MAX)
                    {
                        status = do_write_command(cmd, builder, &packet,
                                                  &force_stop);
                        i2c_command_pending = true;
                    }
                    else
                    {
                        // Unknown Command
                        ASD_log(ASD_LogLevel_Error, ASD_LogStream_I2C,
                                ASD_LogOption_None,
                                "Encountered unknown i2c command 0x%02x",
                                (int)cmd);
                        status = ST_ERR;
                        break;
                    }

                    if (status != ST_OK)
                        break;

                    // if a i2c command is pending and
                    // either we are done looping through
                    // all commands, or the force stop bit
                    // was set, then we need to also flush
                    // the commands
                    if (i2c_command_pending &&
                        ((packet.used == packet.total) || force_stop))
                    {
                        i2c_command_pending = false;
                        force_stop = false;
                        status = i2c_read_write(state->i2c_handler,
                                                builder->msg_set);
                        if (status != ST_OK)
                        {
                            ASD_log(ASD_LogLevel_Error, ASD_LogStream_I2C,
                                    ASD_LogOption_None,
                                    "i2c_read_write failed, %d, assuming NAK",
                                    status);
                        }
                        status = build_responses(state, &response_cnt, builder,
                                                 (status == ST_OK));
                        if (status != ST_OK)
                        {
                            ASD_log(
                                ASD_LogLevel_Error, ASD_LogStream_I2C,
                                ASD_LogOption_None,
                                "i2c_read_write failed to parse i2c responses"
                                ", %d",
                                status);
                            break;
                        }
                        status = i2c_msg_reset(builder);
                        if (status != ST_OK)
                        {
                            ASD_log(
                                ASD_LogLevel_Error, ASD_LogStream_I2C,
                                ASD_LogOption_None,
                                "i2c_msg_reset failed to reset response builder"
                                ", %d",
                                status);
                            break;
                        }
                    }
                }
            }
        }
    }

    if (status == ST_OK)
    {
        state->out_msg.header.size_lsb = (uint32_t)(response_cnt & 0xFF);
        state->out_msg.header.size_msb = (uint32_t)((response_cnt >> 8) & 0x1F);
        state->out_msg.header.cmd_stat = ASD_SUCCESS;
        status = send_response(state, &state->out_msg);
        if (status != ST_OK)
        {
            ASD_log(ASD_LogLevel_Error | ASD_LogOption_No_Remote,
                    ASD_LogStream_I2C, ASD_LogOption_None,
                    "Failed to send message back on the socket - "
                    "process_i2c_message");
        }
    }
    if (builder)
    {
        i2c_msg_deinitialize(builder);
        free(builder);
    }
    return status;
}