-- 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.

require 'storage.json_types.BlockIO'
local lib_sml = require 'sml.core'
local sd_bus = require 'sd_bus'
local skynet = require 'skynet'
local mctp_lib = require 'mctp_lib'
local callbacks = lib_sml.callbacks
local mctp_infos = lib_sml.mctp_infos

local RET_OK = 0
local RET_ERR = -1

local g_bus = nil
local function get_bus()
    if g_bus then
        return g_bus
    end
    g_bus = sd_bus.open_user(false, true)
    return g_bus
end

-- 提供给lib库的mctp读写函数
local MCTP_MESSAGE_TYPE_VDPCI<const> = mctp_lib.MCTP_MESSAGE_TYPE_VDPCI
local function do_mctp_writeread(obj_index, data, wait_response, timeout)
    local phy_addr, vendor_id = mctp_infos.get_mctp_info(obj_index)

    local ok, ep = pcall(mctp_lib.get_pcie_endpoint, get_bus(), phy_addr, MCTP_MESSAGE_TYPE_VDPCI)
    if not ok then
        error('get mctp endpoint failed' .. ep)
    end

    local req_data = string.pack('I2', vendor_id) .. data
    if wait_response then
        local rsp = ep:Request({}, req_data, math.floor(timeout / 1000), {}, {}) -- timeout 是微秒，需要转换为毫秒
        return rsp:sub(3)
    else
        ep:Send({}, req_data, {})
        return ''
    end
end

local function mctp_writeread(...)
    local ok, data = pcall(do_mctp_writeread, ...)
    if not ok then
        skynet.error(data)
        return RET_ERR, ''
    end
    return RET_OK, data
end


return function(work)
    local cbs = callbacks.new()
    local cmd
    while true do
        cmd = work:recv()
        if cmd == 'stop' then
            break
        elseif string.find(cmd, "install_mctp_writeread_cb") then
            cbs:set_mctp_writeread_cb(tonumber(string.match(cmd, "%d+$")), mctp_writeread)
        end
    end
end
