root/drivers/net/wireless/intel/iwlwifi/fw/dhc-utils.h
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
 * Copyright (C) 2021, 2025 Intel Corporation
 */
#ifndef __iwl_fw_dhc_utils_h__
#define __iwl_fw_dhc_utils_h__

#include <linux/types.h>
#include "fw/img.h"
#include "api/commands.h"
#include "api/dhc.h"

/**
 * iwl_dhc_resp_status - return status of DHC response
 * @fw: firwmware image information
 * @pkt: response packet, must not be %NULL
 *
 * Returns: the status value of the DHC command or (u32)-1 if the
 *          response was too short.
 */
static inline u32 iwl_dhc_resp_status(const struct iwl_fw *fw,
                                      struct iwl_rx_packet *pkt)
{
        if (iwl_fw_lookup_notif_ver(fw, IWL_ALWAYS_LONG_GROUP,
                                    DEBUG_HOST_COMMAND, 1) >= 2) {
                struct iwl_dhc_cmd_resp *resp = (void *)pkt->data;

                if (iwl_rx_packet_payload_len(pkt) < sizeof(*resp))
                        return (u32)-1;

                return le32_to_cpu(resp->status);
        } else {
                struct iwl_dhc_cmd_resp_v1 *resp = (void *)pkt->data;

                if (iwl_rx_packet_payload_len(pkt) < sizeof(*resp))
                        return (u32)-1;

                return le32_to_cpu(resp->status);
        }
}

/**
 * iwl_dhc_resp_data - return data pointer of DHC response
 * @fw: firwmware image information
 * @pkt: response packet, must not be %NULL
 * @len: where to store the length
 *
 * Returns: The data pointer, or an ERR_PTR() if the data was
 *          not valid (too short).
 */
static inline void *iwl_dhc_resp_data(const struct iwl_fw *fw,
                                      struct iwl_rx_packet *pkt,
                                      unsigned int *len)
{
        if (iwl_fw_lookup_notif_ver(fw, IWL_ALWAYS_LONG_GROUP,
                                    DEBUG_HOST_COMMAND, 1) >= 2) {
                struct iwl_dhc_cmd_resp *resp = (void *)pkt->data;

                if (iwl_rx_packet_payload_len(pkt) < sizeof(*resp))
                        return ERR_PTR(-EINVAL);

                *len = iwl_rx_packet_payload_len(pkt) - sizeof(*resp);
                return (void *)&resp->data;
        } else {
                struct iwl_dhc_cmd_resp_v1 *resp = (void *)pkt->data;

                if (iwl_rx_packet_payload_len(pkt) < sizeof(*resp))
                        return ERR_PTR(-EINVAL);

                *len = iwl_rx_packet_payload_len(pkt) - sizeof(*resp);
                return (void *)&resp->data;
        }
}

#endif  /* __iwl_fw_dhc_utils_h__ */