-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under 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.


local bs = require 'mc.bitstring'
local def = require 'device.lib_pcie_oob_mgmt.def'

local st = {}

-- 请求
local bs_request = bs.new([[<<
    _:16,
    command:16,
    offset:32,
    read_length:32,
    crc:32
>>]]) -- 16 Bytes

-- 响应
-- total_length: 所有帧有效数据长度总和
-- data_length: 是当前帧data部分长度（不一定都是有效数据）
local bs_response = bs.new([[<<
    error_code:16,
    opcode:16,
    total_length:32,
    data_length:32,
    data/string
>>]]) -- 12+n Bytes

-- 能力码
local bs_capability = bs.new([[<<
    id:16,
    type:8,
    _:8,
    opcode_num:16,
    opcodes/string
>>]]) -- 6+n Bytes

-- 固件版本
local bs_firmware_version = bs.new([[<<
    major:8,
    minor:8,
    revision:8
>>]]) -- 3 Bytes

-- 健康状态
local bs_health = bs.new([[<<
    health:8
>>]]) -- 1 Bytes

-- 格式：{bs定义, 结构体长度, 处理函数}
local struct_map = {
    ['request'] = {bs_request, 16},
    ['response'] = {bs_response, 13},
    [def.e_opcode.CAPABILITY] = {bs_capability, 7},
    [def.e_opcode.GET_HEALTH] = {bs_health, 1},
    [def.e_opcode.GET_FIRMWARE_VERSION] = {bs_firmware_version, 3}
}

local function get_struct(name)
    local bs_struct = struct_map[name][1]
    local len = struct_map[name][2]
    local struct = {
        bs_struct = bs_struct,
        len = len,
        new = function ()
            return bs_struct:unpack(string.pack('c' .. len, ''))
        end,
        pack = function (item)
            return bs_struct:pack(item)
        end,
        unpack = function (item)
            return bs_struct:unpack(item)
        end
    }
    if struct_map[name][3] then
        struct_map[name][3](struct)
    end
    return struct
end

st.get_struct = get_struct
st.request = get_struct('request')
st.response = get_struct('response')

return st