-- Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
-- 
-- this file licensed under the Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2
--
-- THIS SOFTWARE IS PROVIDED ON AN \"AS IS\" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
-- PURPOSE.
-- See the Mulan PSL v2 for more details.
-- qlogic卡使用此协议获取fru信息

local class = require 'mc.class'
local bs = require 'mc.bitstring'
local log = require 'mc.logging'
local pldm_standard = require 'protocol_open.protocol.pldm_standard'

local pldm_qlogic_fru = class(pldm_standard)
local QLOGIC_PLDM_TYPE_FOR_FRU_DATA<const> = 0x04
local QLOGIC_CMD_CODE_GET_FRU_RECORD_BY_OPTION<const> = 0x04
local QLOGIC_FRU_RECORD_SET_ID<const> = 0x1077
local QLOGIC_FRU_GET_FIRST_PART<const> = 0x01
local RESPANSE_HDR_LENGTH = 12 -- rsp里除data之外数据的长度

local response_bs<const> = bs.new([[<<
    next_data_transfer_handle:32,
    transfer_flag:8,
    record_id:16,
    record_type:8,
    number_field:8,
    encoding_type:8,
    field_type:8,
    field_len:8,
    data/string
>>]])

local request_bs<const> = bs.new([[<<
    data_transfer_handle:32,
    fru_table_handle:16,
    record_set_identifier:16,
    record_type:8,
    field_type:8,
    transfer_operation_flag:8
>>]])

local request_params_template<const> = {record_type = true, field_type = true}

function pldm_qlogic_fru:construct_request_data(ctx, request)
    if request.record_type == nil or request.field_type == nil then
        return {}
    end
    local data = request_bs:pack({
        data_transfer_handle = 0x00,
        fru_table_handle = 0x00,
        record_set_identifier = QLOGIC_FRU_RECORD_SET_ID,
        record_type = request.record_type,
        field_type = request.field_type,
        transfer_operation_flag = QLOGIC_FRU_GET_FIRST_PART
    })
    return pldm_qlogic_fru.super.construct_request_data(self, ctx, {
        pldm_type = QLOGIC_PLDM_TYPE_FOR_FRU_DATA,
        command_code = QLOGIC_CMD_CODE_GET_FRU_RECORD_BY_OPTION,
        rsp_command_code = QLOGIC_CMD_CODE_GET_FRU_RECORD_BY_OPTION, -- pldm的rsp command code与req command code一致
        data = data
    })
end

function pldm_qlogic_fru:unpack_response_data(ctx, rsp_bin)
    if ctx.completion_code and ctx.completion_code ~= 0 then
        log:debug(
            '[protocol %s]: unsuccessful request with completion_code: %s',
            self.name, ctx.completion_code)
        return nil
    end

    local rsp = response_bs:unpack(rsp_bin, true)
    if #rsp_bin - RESPANSE_HDR_LENGTH < rsp.field_len then
        log:debug('[protocol %s]: invalid recv data len:%s, expect:%s ',
            self.name, #rsp_bin - RESPANSE_HDR_LENGTH, rsp.field_len)
        return nil
    end
    if not rsp or not rsp.data then
        log:debug('[protocol %s]: empty data received', self.name)
        return nil
    end
    return rsp.data:sub(1, rsp.field_len)
end

function pldm_qlogic_fru:ctor()
    self.name = 'pldm_qlogic_fru'
    self.request_params_template = request_params_template
end

return pldm_qlogic_fru
