// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "device.h"

#include "probe_sequence.h"

#include <ddk/device.h>
#include <lib/zx/thread.h>
#include <lib/zx/time.h>
#include <wlan/common/channel.h>
#include <wlan/common/logging.h>
#include <wlan/mlme/ap/ap_mlme.h>
#include <wlan/mlme/client/bss.h>
#include <wlan/mlme/client/client_mlme.h>
#include <wlan/mlme/debug.h>
#include <wlan/mlme/mesh/mesh_mlme.h>
#include <wlan/mlme/service.h>
#include <wlan/mlme/timer.h>
#include <wlan/mlme/timer_manager.h>
#include <wlan/mlme/validate_frame.h>
#include <wlan/mlme/wlan.h>
#include <wlan/protocol/ioctl.h>
#include <zircon/assert.h>
#include <zircon/compiler.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/port.h>

#include <cinttypes>
#include <cstdarg>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <limits>
#include <utility>

namespace wlan {

namespace wlan_minstrel = ::fuchsia::wlan::minstrel;

// Remedy for FLK-24 (DNO-389)
// See |MINSTREL_DATA_FRAME_INTERVAL_NANOS| in //garnet/bin/wlan-hw-sim/src/main.rs
// For the test, ensure at least one probe frame (generated every 16 data frames) in every cycle,
// 16 <= (kMinstrelUpdateIntervalForHwSim / MINSTREL_DATA_FRAME_INTERVAL_NANOS * 1e6) < 32.
static constexpr zx::duration kMinstrelUpdateIntervalForHwSim = zx::msec(83);
static constexpr zx::duration kMinstrelUpdateIntervalNormal = zx::msec(100);

#define DEV(c) static_cast<Device*>(c)
static zx_protocol_device_t wlan_device_ops = {
    .version = DEVICE_OPS_VERSION,
    .unbind = [](void* ctx) { DEV(ctx)->WlanUnbind(); },
    .release = [](void* ctx) { DEV(ctx)->WlanRelease(); },
    .ioctl = [](void* ctx, uint32_t op, const void* in_buf, size_t in_len, void* out_buf,
                size_t out_len, size_t* out_actual) -> zx_status_t {
        return DEV(ctx)->WlanIoctl(op, in_buf, in_len, out_buf, out_len, out_actual);
    },
};

static zx_protocol_device_t eth_device_ops = {
    .version = DEVICE_OPS_VERSION,
    .unbind = [](void* ctx) { DEV(ctx)->EthUnbind(); },
    .release = [](void* ctx) { DEV(ctx)->EthRelease(); },
};

static wlanmac_ifc_t wlanmac_ifc_ops = {
    .status = [](void* cookie, uint32_t status) { DEV(cookie)->WlanmacStatus(status); },
    .recv = [](void* cookie, uint32_t flags, const void* data, size_t length,
               wlan_rx_info_t* info) { DEV(cookie)->WlanmacRecv(flags, data, length, info); },
    .complete_tx = [](void* cookie, wlan_tx_packet_t* pkt,
                      zx_status_t status) { DEV(cookie)->WlanmacCompleteTx(pkt, status); },
    .indication = [](void* cookie, uint32_t ind) { DEV(cookie)->WlanmacIndication(ind); },
    .report_tx_status =
        [](void* cookie, const wlan_tx_status_t* tx_status) {
            DEV(cookie)->WlanmacReportTxStatus(tx_status);
        },
    .hw_scan_complete =
        [](void* cookie, const wlan_hw_scan_result_t* result) {
            DEV(cookie)->WlanmacHwScanComplete(result);
        },
};

static ethmac_protocol_ops_t ethmac_ops = {
    .query = [](void* ctx, uint32_t options, ethmac_info_t* info) -> zx_status_t {
        return DEV(ctx)->EthmacQuery(options, info);
    },
    .stop = [](void* ctx) { DEV(ctx)->EthmacStop(); },
    .start = [](void* ctx, const ethmac_ifc_t* ifc) -> zx_status_t {
        return DEV(ctx)->EthmacStart(ifc);
    },
    .queue_tx = [](void* ctx, uint32_t options, ethmac_netbuf_t* netbuf) -> zx_status_t {
        return DEV(ctx)->EthmacQueueTx(options, netbuf);
    },
    .set_param = [](void* ctx, uint32_t param, int32_t value, const void* data, size_t data_size)
        -> zx_status_t { return DEV(ctx)->EthmacSetParam(param, value, data, data_size); },
};
#undef DEV

Device::Device(zx_device_t* device, wlanmac_protocol_t wlanmac_proto,
               std::shared_ptr<component::Services> services)
    : parent_(device),
      wlanmac_proxy_(wlanmac_proto),
      services_(services),
      fidl_msg_buf_(ZX_CHANNEL_MAX_MSG_BYTES) {
    debugfn();
    state_ = fbl::AdoptRef(new DeviceState);
}

Device::~Device() {
    debugfn();
    ZX_DEBUG_ASSERT(!work_thread_.joinable());
}

// Disable thread safety analysis, as this is a part of device initialization. All thread-unsafe
// work should occur before multiple threads are possible (e.g., before MainLoop is started and
// before DdkAdd() is called), or locks should be held.
zx_status_t Device::Bind() __TA_NO_THREAD_SAFETY_ANALYSIS {
    debugfn();

    zx_status_t status = zx::port::create(0, &port_);
    if (status != ZX_OK) {
        errorf("could not create port: %d\n", status);
        return status;
    }

    status = wlanmac_proxy_.Query(0, &wlanmac_info_);
    if (status != ZX_OK) {
        errorf("could not query wlanmac device: %d\n", status);
        return status;
    }

    status = ValidateWlanMacInfo(wlanmac_info_);
    if (status != ZX_OK) {
        errorf("could not bind wlanmac device with invalid wlanmac info\n");
        return status;
    }

    status = wlanmac_proxy_.Start(&wlanmac_ifc_ops, this);
    if (status != ZX_OK) {
        errorf("failed to start wlanmac device: %s\n", zx_status_get_string(status));
        return status;
    }

    state_->set_address(common::MacAddr(wlanmac_info_.ifc_info.mac_addr));

    fbl::unique_ptr<Mlme> mlme;

    // mac_role is a bitfield, but only a single value is supported for an interface
    switch (wlanmac_info_.ifc_info.mac_role) {
    case WLAN_MAC_ROLE_CLIENT:
        infof("Initialize a client MLME.\n");
        mlme.reset(new ClientMlme(this));
        break;
    case WLAN_MAC_ROLE_AP:
        infof("Initialize an AP MLME.\n");
        mlme.reset(new ApMlme(this));
        break;
    case WLAN_MAC_ROLE_MESH:
        infof("Initialize a mesh MLME.\n");
        mlme.reset(new MeshMlme(this));
        break;
    default:
        errorf("unsupported MAC role: %u\n", wlanmac_info_.ifc_info.mac_role);
        return ZX_ERR_NOT_SUPPORTED;
    }
    ZX_DEBUG_ASSERT(mlme != nullptr);
    status = mlme->Init();
    if (status != ZX_OK) {
        errorf("could not initialize MLME: %d\n", status);
        return status;
    }
    dispatcher_.reset(new Dispatcher(this, std::move(mlme)));
    if (ShouldEnableMinstrel()) {
        zx_status_t status = CreateMinstrel(wlanmac_info_.ifc_info.driver_features);
        if (ZX_OK == status) { debugmstl("Minstrel Manager created successfully.\n"); }
    }

    work_thread_ = std::thread(&Device::MainLoop, this);

    bool wlan_added = false;

    status = AddWlanDevice();
    if (status == ZX_OK) {
        wlan_added = true;
        status = AddEthDevice();
    }

    // Clean up if either device add failed.
    if (status != ZX_OK) {
        errorf("could not add device err=%d\n", status);
        zx_status_t shutdown_status = QueueDevicePortPacket(DevicePacket::kShutdown);
        if (shutdown_status != ZX_OK) {
            ZX_PANIC("wlan: could not send shutdown loop message: %d\n", shutdown_status);
        }
        if (work_thread_.joinable()) { work_thread_.join(); }

        // Remove the wlan device if it was successfully added.
        if (wlan_added) { device_remove(zxdev_); }
    } else {
        debugf("device added\n");
    }

    return status;
}

zx_status_t Device::AddWlanDevice() {
    device_add_args_t args = {};
    args.version = DEVICE_ADD_ARGS_VERSION;
    args.name = "wlan";
    args.ctx = this;
    args.ops = &wlan_device_ops;
    args.proto_id = ZX_PROTOCOL_WLANIF;
    return device_add(parent_, &args, &zxdev_);
}

zx_status_t Device::AddEthDevice() {
    device_add_args_t args = {};
    args.version = DEVICE_ADD_ARGS_VERSION;
    args.name = "wlan-ethernet";
    args.ctx = this;
    args.ops = &eth_device_ops;
    args.proto_id = ZX_PROTOCOL_ETHMAC;
    args.proto_ops = &ethmac_ops;
    return device_add(zxdev_, &args, &ethdev_);
}

fbl::unique_ptr<Packet> Device::PreparePacket(const void* data, size_t length, Packet::Peer peer) {
    fbl::unique_ptr<Buffer> buffer = GetBuffer(length);
    if (buffer == nullptr) {
        errorf("could not get buffer for packet of length %zu\n", length);
        return nullptr;
    }

    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), length));
    packet->set_peer(peer);
    zx_status_t status = packet->CopyFrom(data, length, 0);
    if (status != ZX_OK) {
        errorf("could not copy to packet: %d\n", status);
        return nullptr;
    }
    return packet;
}

zx_status_t Device::QueuePacket(fbl::unique_ptr<Packet> packet) {
    if (packet == nullptr) { return ZX_ERR_NO_RESOURCES; }
    std::lock_guard<std::mutex> lock(packet_queue_lock_);
    bool was_empty = packet_queue_.is_empty();
    packet_queue_.Enqueue(std::move(packet));

    if (was_empty) {
        zx_status_t status = QueueDevicePortPacket(DevicePacket::kPacketQueued);
        if (status != ZX_OK) {
            errorf("could not send packet queued msg err=%d\n", status);
            packet_queue_.UndoEnqueue();
            return status;
        }
    }
    return ZX_OK;
}

void Device::WlanUnbind() {
    debugfn();
    {
        std::lock_guard<std::mutex> lock(lock_);
        channel_.reset();
        dead_ = true;
        if (port_.is_valid()) {
            zx_status_t status = QueueDevicePortPacket(DevicePacket::kShutdown);
            if (status != ZX_OK) {
                ZX_PANIC("wlan: could not send shutdown loop message: %d\n", status);
            }
        }
    }
    device_remove(zxdev_);
}

void Device::WlanRelease() {
    debugfn();
    if (work_thread_.joinable()) { work_thread_.join(); }
    delete this;
}

zx_status_t Device::WlanIoctl(uint32_t op, const void* in_buf, size_t in_len, void* out_buf,
                              size_t out_len, size_t* out_actual) {
    debugfn();
    if (op != IOCTL_WLAN_GET_CHANNEL) { return ZX_ERR_NOT_SUPPORTED; }
    if (out_buf == nullptr || out_actual == nullptr || out_len < sizeof(zx_handle_t)) {
        return ZX_ERR_BUFFER_TOO_SMALL;
    }

    zx::channel out;
    zx_status_t status = GetChannel(&out);
    if (status != ZX_OK) { return status; }

    zx_handle_t* outh = static_cast<zx_handle_t*>(out_buf);
    *outh = out.release();
    *out_actual = sizeof(zx_handle_t);
    return ZX_OK;
}

void Device::EthUnbind() {
    debugfn();
    device_remove(ethdev_);
}

void Device::EthRelease() {
    debugfn();
    // NOTE: we reuse the same ctx for the wlanif and the ethmac, so we do NOT free the memory here.
    // Since ethdev_ is a child of zxdev_, this release will be called first, followed by
    // WlanRelease. There's nothing else to clean up here.
}

zx_status_t Device::EthmacQuery(uint32_t options, ethmac_info_t* info) {
    debugfn();
    if (info == nullptr) return ZX_ERR_INVALID_ARGS;

    memset(info, 0, sizeof(*info));
    memcpy(info->mac, wlanmac_info_.ifc_info.mac_addr, ETH_MAC_SIZE);
    info->features = ETHMAC_FEATURE_WLAN;
    if (wlanmac_info_.ifc_info.driver_features & WLAN_DRIVER_FEATURE_SYNTH) {
        info->features |= ETHMAC_FEATURE_SYNTH;
    }
    info->mtu = 1500;
    info->netbuf_size = sizeof(ethmac_netbuf_t);

    return ZX_OK;
}

zx_status_t Device::EthmacStart(const ethmac_ifc_t* ifc) {
    debugfn();
    ZX_DEBUG_ASSERT(ifc != nullptr);

    std::lock_guard<std::mutex> lock(lock_);
    if (ethmac_proxy_ != nullptr) { return ZX_ERR_ALREADY_BOUND; }
    ethmac_proxy_.reset(new ddk::EthmacIfcClient(ifc));
    return ZX_OK;
}

void Device::EthmacStop() {
    debugfn();

    std::lock_guard<std::mutex> lock(lock_);
    if (ethmac_proxy_ == nullptr) { warnf("ethmac not started\n"); }
    ethmac_proxy_.reset();
}

zx_status_t Device::EthmacQueueTx(uint32_t options, ethmac_netbuf_t* netbuf) {
    // no debugfn() because it's too noisy
    auto packet = PreparePacket(netbuf->data_buffer, netbuf->data_size, Packet::Peer::kEthernet);
    if (packet == nullptr) {
        warnf("could not prepare Ethernet packet with len %zu\n", netbuf->data_size);
        return ZX_ERR_NO_RESOURCES;
    }
    zx_status_t status = QueuePacket(std::move(packet));
    if (status != ZX_OK) { warnf("could not queue Ethernet packet err=%d\n", status); }
    return status;
}

zx_status_t Device::EthmacSetParam(uint32_t param, int32_t value, const void* data,
                                   size_t data_size) {
    debugfn();

    zx_status_t status = ZX_ERR_NOT_SUPPORTED;

    switch (param) {
    case ETHMAC_SETPARAM_PROMISC:
        // See NET-1808: In short, the bridge mode doesn't require WLAN promiscuous mode enabled.
        //               So we give a warning and return OK here to continue the bridging.
        // TODO(NET-1930): To implement the real promiscuous mode.
        if (value == 1) {  // Only warn when enabling.
            warnf("WLAN promiscuous not supported yet. see NET-1930\n");
        }
        status = ZX_OK;
        break;
    }

    return status;
}

void Device::WlanmacStatus(uint32_t status) {
    debugf("WlanmacStatus %u\n", status);

    std::lock_guard<std::mutex> lock(lock_);
    SetStatusLocked(status);
}

void Device::WlanmacRecv(uint32_t flags, const void* data, size_t length, wlan_rx_info_t* info) {
    // no debugfn() because it's too noisy
    auto packet = PreparePacket(data, length, Packet::Peer::kWlan, *info);
    if (packet == nullptr) {
        errorf("could not prepare outbound Ethernet packet with len %zu\n", length);
        return;
    }

    zx_status_t status = QueuePacket(std::move(packet));
    if (status != ZX_OK) {
        warnf("could not queue inbound packet with len %zu err=%d\n", length, status);
    }
}

void Device::WlanmacCompleteTx(wlan_tx_packet_t* pkt, zx_status_t status) {
    // TODO(tkilbourn): free memory and complete the ethernet tx (if necessary). For now, we aren't
    // doing any async transmits in the wlan drivers, so this method shouldn't be called yet.
    ZX_PANIC("not implemented yet!");
}

void Device::WlanmacIndication(uint32_t ind) {
    debugf("WlanmacIndication %u\n", ind);
    auto status = QueueDevicePortPacket(DevicePacket::kIndication, ind);
    if (status != ZX_OK) { warnf("could not queue driver indication packet err=%d\n", status); }
}

void Device::WlanmacReportTxStatus(const wlan_tx_status_t* tx_status) {
    ZX_DEBUG_ASSERT(minstrel_ != nullptr);
    if (minstrel_ != nullptr) { minstrel_->HandleTxStatusReport(*tx_status); }
}

void Device::WlanmacHwScanComplete(const wlan_hw_scan_result_t* result) {
    debugf("WlanmacHwScanComplete %u\n", result->code);
    auto status = QueueDevicePortPacket(DevicePacket::kHwScanComplete, result->code);
    if (status != ZX_OK) { errorf("could not queue hw scan complete packet err=%d\n", status); }
}

zx_status_t Device::GetTimer(uint64_t id, fbl::unique_ptr<Timer>* timer) {
    ZX_DEBUG_ASSERT(timer != nullptr);
    ZX_DEBUG_ASSERT(timer->get() == nullptr);
    ZX_DEBUG_ASSERT(port_.is_valid());

    zx::timer t;
    zx_status_t status = zx::timer::create(0u, ZX_CLOCK_MONOTONIC, &t);
    if (status != ZX_OK) { return status; }

    status = t.wait_async(port_, id, ZX_TIMER_SIGNALED, ZX_WAIT_ASYNC_REPEATING);
    if (status != ZX_OK) { return status; }
    timer->reset(new SystemTimer(id, std::move(t)));

    return ZX_OK;
}

zx_status_t Device::DeliverEthernet(Span<const uint8_t> eth_frame) {
    if (eth_frame.size() > ETH_FRAME_MAX_SIZE) {
        errorf("Attempted to deliver an ethernet frame of invalid length: %zu\n", eth_frame.size());
        return ZX_ERR_INVALID_ARGS;
    }

    if (ethmac_proxy_ != nullptr) { ethmac_proxy_->Recv(eth_frame.data(), eth_frame.size(), 0u); }
    return ZX_OK;
}

TxVector GetTxVector(const fbl::unique_ptr<MinstrelRateSelector>& minstrel,
                     const fbl::unique_ptr<Packet>& packet, CBW cbw, PHY phy, uint32_t flags) {
    const auto fc = packet->field<FrameControl>(0);

    constexpr size_t kAddr1Offset = 4;
    ZX_DEBUG_ASSERT(packet->len() >= kAddr1Offset + common::kMacAddrLen);
    auto peer_addr = common::MacAddr(packet->field<uint8_t>(kAddr1Offset));

    if (minstrel != nullptr) {
        tx_vec_idx_t idx = minstrel->GetTxVectorIdx(*fc, peer_addr, flags);
        TxVector tv;
        zx_status_t status = TxVector::FromIdx(idx, &tv);
        ZX_DEBUG_ASSERT(status == ZX_OK);
        return tv;
    } else {
        // TODO(NET-645): Choose an optimal MCS for management frames
        uint8_t mcs = fc->type() == FrameType::kData ? 7 : 3;
        return {
            .phy = static_cast<PHY>(phy),
            .cbw = static_cast<CBW>(cbw),
            .mcs_idx = mcs,
            .nss = 1,
            .gi = WLAN_GI_800NS,
        };
    }
}

wlan_tx_info_t MakeTxInfo(const fbl::unique_ptr<Packet>& packet, const TxVector& tv,
                          uint32_t has_minstrel, uint32_t flags) {
    tx_vec_idx_t idx;
    zx_status_t status = tv.ToIdx(&idx);
    ZX_DEBUG_ASSERT(status == ZX_OK);

    uint32_t valid_fields =
        WLAN_TX_INFO_VALID_PHY | WLAN_TX_INFO_VALID_CHAN_WIDTH | WLAN_TX_INFO_VALID_MCS;
    if (has_minstrel) { valid_fields |= WLAN_TX_INFO_VALID_TX_VECTOR_IDX; }

    const auto fc = packet->field<FrameControl>(0);
    if (fc->protected_frame()) { flags |= WLAN_TX_INFO_FLAGS_PROTECTED; }

    return {
        .phy = static_cast<uint16_t>(tv.phy),
        .cbw = static_cast<uint8_t>(tv.cbw),
        .mcs = tv.mcs_idx,
        .tx_vector_idx = idx,
        .valid_fields = valid_fields,
        .tx_flags = flags,
    };
}

zx_status_t Device::SendWlan(fbl::unique_ptr<Packet> packet, CBW cbw, PHY phy, uint32_t flags) {
    ZX_DEBUG_ASSERT(packet->len() <= std::numeric_limits<uint16_t>::max());
    ZX_DEBUG_ASSERT(ValidateFrame("Transmitting a malformed frame", *packet));

    auto tv = GetTxVector(minstrel_, packet, cbw, phy, flags);
    packet->CopyCtrlFrom(MakeTxInfo(packet, tv, minstrel_ != nullptr, flags));
    wlan_tx_packet_t tx_pkt = packet->AsWlanTxPacket();
    auto status = wlanmac_proxy_.QueueTx(0u, &tx_pkt);
    // TODO(tkilbourn): remove this once we implement WlanmacCompleteTx and allow wlanmac drivers to
    // complete transmits asynchronously.
    ZX_DEBUG_ASSERT(status != ZX_ERR_SHOULD_WAIT);

    return status;
}

// Disable thread safety analysis, since these methods are called through an interface from an
// object that we know is holding the lock. So taking the lock would be wrong, but there's no way to
// convince the compiler that the lock is held.

// This *should* be safe, since the worst case is that
// the syscall fails, and we return an error.
// TODO(tkilbourn): consider refactoring this so we don't have to abandon the safety analysis.
zx_status_t Device::SendService(Span<const uint8_t> span) __TA_NO_THREAD_SAFETY_ANALYSIS {
    if (channel_.is_valid()) { return channel_.write(0u, span.data(), span.size(), nullptr, 0); }
    return ZX_OK;
}

// TODO(tkilbourn): figure out how to make sure we have the lock for accessing dispatcher_.
zx_status_t Device::SetChannel(wlan_channel_t chan) __TA_NO_THREAD_SAFETY_ANALYSIS {
    // TODO(porce): Implement == operator for wlan_channel_t, or an equality test function.

    char buf[80];
    snprintf(buf, sizeof(buf), "channel set: from %s to %s",
             common::ChanStr(state_->channel()).c_str(), common::ChanStr(chan).c_str());

    if (chan.primary == state_->channel().primary && chan.cbw == state_->channel().cbw) {
        warnf("%s suppressed\n", buf);
        return ZX_OK;
    }

    zx_status_t status = wlanmac_proxy_.SetChannel(0u, &chan);
    if (status != ZX_OK) {
        errorf("%s change failed (status %d)\n", buf, status);
        return status;
    }

    state_->set_channel(chan);

    verbosef("%s succeeded\n", buf);
    return ZX_OK;
}

zx_status_t Device::SetStatus(uint32_t status) {
    // Lock is already held when MLME is asked to handle assoc/deassoc packets, which caused this
    // link status change.
    SetStatusLocked(status);
    return ZX_OK;
}

void Device::SetStatusLocked(uint32_t status) {
    state_->set_online(status == ETHMAC_STATUS_ONLINE);
    if (ethmac_proxy_ != nullptr) { ethmac_proxy_->Status(status); }
}

zx_status_t Device::ConfigureBss(wlan_bss_config_t* cfg) {
    return wlanmac_proxy_.ConfigureBss(0u, cfg);
}

zx_status_t Device::EnableBeaconing(wlan_bcn_config_t* bcn_cfg) {
    if (bcn_cfg != nullptr) {
        ZX_DEBUG_ASSERT(
            ValidateFrame("Malformed beacon template",
                          {reinterpret_cast<const uint8_t*>(bcn_cfg->tmpl.packet_head.data_buffer),
                           bcn_cfg->tmpl.packet_head.data_size}));
    }
    return wlanmac_proxy_.EnableBeaconing(0u, bcn_cfg);
}

zx_status_t Device::ConfigureBeacon(fbl::unique_ptr<Packet> beacon) {
    ZX_DEBUG_ASSERT(beacon.get() != nullptr);
    if (beacon.get() == nullptr) { return ZX_ERR_INVALID_ARGS; }

    ZX_DEBUG_ASSERT(ValidateFrame("Malformed beacon template", *beacon));

    wlan_tx_packet_t tx_packet = beacon->AsWlanTxPacket();
    return wlanmac_proxy_.ConfigureBeacon(0u, &tx_packet);
}

zx_status_t Device::SetKey(wlan_key_config_t* key_config) {
    return wlanmac_proxy_.SetKey(0u, key_config);
}

zx_status_t Device::StartHwScan(const wlan_hw_scan_config_t* scan_config) {
    return wlanmac_proxy_.StartHwScan(scan_config);
}

zx_status_t Device::ConfigureAssoc(wlan_assoc_ctx_t* assoc_ctx) {
    ZX_DEBUG_ASSERT(assoc_ctx != nullptr);
    // TODO(NET-1385): Minstrel only supports client mode. Add AP mode support later.
    AddMinstrelPeer(*assoc_ctx);
    return wlanmac_proxy_.ConfigureAssoc(0u, assoc_ctx);
}

zx_status_t Device::ClearAssoc(const wlan::common::MacAddr& peer_addr) {
    if (minstrel_ != nullptr) { minstrel_->RemovePeer(peer_addr); }

    uint8_t mac[wlan::common::kMacAddrLen];
    peer_addr.CopyTo(mac);
    return wlanmac_proxy_.ClearAssoc(0u, mac);
}

fbl::RefPtr<DeviceState> Device::GetState() {
    return state_;
}

const wlanmac_info_t& Device::GetWlanInfo() const {
    return wlanmac_info_;
}

zx_status_t Device::GetMinstrelPeers(wlan_minstrel::Peers* peers_fidl) {
    if (minstrel_ == nullptr) { return ZX_ERR_NOT_SUPPORTED; }
    return minstrel_->GetListToFidl(peers_fidl);
}

zx_status_t Device::GetMinstrelStats(const common::MacAddr& addr, wlan_minstrel::Peer* peer_fidl) {
    if (minstrel_ == nullptr) { return ZX_ERR_NOT_SUPPORTED; }
    return minstrel_->GetStatsToFidl(addr, peer_fidl);
}

void Device::MainLoop() {
    infof("starting MainLoop\n");
    const char kThreadName[] = "wlan-mainloop";
    zx::thread::self()->set_property(ZX_PROP_NAME, kThreadName, sizeof(kThreadName));

    zx_port_packet_t pkt;
    bool running = true;
    while (running) {
        zx::time timeout = zx::deadline_after(zx::sec(30));
        zx_status_t status = port_.wait(timeout, &pkt);
        std::lock_guard<std::mutex> lock(lock_);
        if (status == ZX_ERR_TIMED_OUT) {
            // TODO(tkilbourn): more watchdog checks here?
            ZX_DEBUG_ASSERT(running);
            continue;
        } else if (status != ZX_OK) {
            if (status == ZX_ERR_BAD_HANDLE) {
                debugf("port closed, exiting\n");
            } else {
                errorf("error waiting on port: %d\n", status);
            }
            break;
        }

        switch (pkt.type) {
        case ZX_PKT_TYPE_USER:
            ZX_DEBUG_ASSERT(ToPortKeyType(pkt.key) == PortKeyType::kDevice);
            switch (ToPortKeyId(pkt.key)) {
            case to_enum_type(DevicePacket::kShutdown):
                running = false;
                continue;
            case to_enum_type(DevicePacket::kIndication):
                dispatcher_->HwIndication(pkt.status);
                break;
            case to_enum_type(DevicePacket::kHwScanComplete):
                dispatcher_->HwScanComplete(pkt.status);
                break;
            case to_enum_type(DevicePacket::kPacketQueued): {
                PacketQueue queued_packets{};
                {
                    std::lock_guard<std::mutex> lock(packet_queue_lock_);
                    queued_packets = packet_queue_.Drain();
                }
                while (!queued_packets.is_empty()) {
                    auto packet = queued_packets.Dequeue();
                    ZX_DEBUG_ASSERT(packet != nullptr);
                    zx_status_t status = dispatcher_->HandlePacket(std::move(packet));
                    if (status != ZX_OK) { errorf("could not handle packet err=%d\n", status); }
                }
                break;
            }
            default:
                errorf("unknown device port key subtype: %" PRIu64 "\n", pkt.user.u64[0]);
                break;
            }
            break;
        case ZX_PKT_TYPE_SIGNAL_REP:
            switch (ToPortKeyType(pkt.key)) {
            case PortKeyType::kMlme:
                dispatcher_->HandlePortPacket(pkt.key);
                break;
            case PortKeyType::kDevice: {
                ZX_DEBUG_ASSERT(minstrel_ != nullptr);
                minstrel_->HandleTimeout();
                break;
            }
            default:
                errorf("unknown port key: %" PRIu64 "\n", pkt.key);
                break;
            }
            break;
        case ZX_PKT_TYPE_SIGNAL_ONE:
            switch (ToPortKeyType(pkt.key)) {
            case PortKeyType::kService:
                ProcessChannelPacketLocked(pkt.signal.count);
                break;
            default:
                errorf("unknown port key: %" PRIu64 "\n", pkt.key);
                break;
            }
            break;
        default:
            errorf("unknown port packet type: %u\n", pkt.type);
            break;
        }
    }

    infof("exiting MainLoop\n");
    std::lock_guard<std::mutex> lock(lock_);
    port_.reset();
    channel_.reset();
}

void Device::ProcessChannelPacketLocked(uint64_t signal_count) {
    if (!channel_.is_valid()) {
        // It could be that we closed the channel (e.g., in WlanUnbind()) but there is still
        // a pending packet in the port that indicates read availability on that channel.
        // In that case we simply ignore the packet since we can't read from the channel anyway.
        return;
    }

    for (size_t i = 0; i < signal_count; ++i) {
        uint32_t read = 0;
        zx_status_t status = channel_.read(0, fidl_msg_buf_.data(), fidl_msg_buf_.size(), &read,
                                           nullptr, 0, nullptr);
        if (status == ZX_ERR_SHOULD_WAIT) { break; }
        if (status != ZX_OK) {
            if (status == ZX_ERR_PEER_CLOSED) {
                infof("channel closed\n");
            } else {
                errorf("could not read channel: %s\n", zx_status_get_string(status));
            }
            channel_.reset();
            return;
        }

        status = dispatcher_->HandleAnyMlmeMessage({fidl_msg_buf_.data(), read});
        if (status != ZX_OK) {
            errorf("Could not handle service packet: %s\n", zx_status_get_string(status));
        }
    }
    RegisterChannelWaitLocked();
}

zx_status_t Device::RegisterChannelWaitLocked() {
    zx_signals_t sigs = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
    return channel_.wait_async(port_, ToPortKey(PortKeyType::kService, 0u), sigs,
                               ZX_WAIT_ASYNC_ONCE);
}

zx_status_t Device::QueueDevicePortPacket(DevicePacket id, uint32_t status) {
    debugfn();
    zx_port_packet_t pkt = {};
    pkt.key = ToPortKey(PortKeyType::kDevice, to_enum_type(id));
    pkt.type = ZX_PKT_TYPE_USER;
    pkt.status = status;
    if (!port_.is_valid()) { return ZX_ERR_BAD_STATE; }
    return port_.queue(&pkt);
}

zx_status_t Device::GetChannel(zx::channel* out) {
    ZX_DEBUG_ASSERT(out != nullptr);

    std::lock_guard<std::mutex> lock(lock_);
    if (dead_) { return ZX_ERR_PEER_CLOSED; }
    if (!port_.is_valid()) { return ZX_ERR_BAD_STATE; }
    if (channel_.is_valid()) { return ZX_ERR_ALREADY_BOUND; }

    zx_status_t status = zx::channel::create(0, &channel_, out);
    if (status != ZX_OK) {
        errorf("could not create channel: %d\n", status);
        return status;
    }

    status = RegisterChannelWaitLocked();
    if (status != ZX_OK) {
        errorf("could not wait on channel: %d\n", status);
        out->reset();
        channel_.reset();
        return status;
    }

    infof("channel opened\n");
    return ZX_OK;
}

zx_status_t ValidateWlanMacInfo(const wlanmac_info& wlanmac_info) {
    for (uint8_t i = 0; i < wlanmac_info.ifc_info.num_bands; i++) {
        auto bandinfo = wlanmac_info.ifc_info.bands[i];

        // Validate channels
        auto& supported_channels = bandinfo.supported_channels;
        switch (supported_channels.base_freq) {
        case common::kBaseFreq5Ghz:
            for (auto c : supported_channels.channels) {
                if (c == 0) {  // End of the valid channel
                    break;
                }
                auto chan = wlan_channel_t{.primary = c, .cbw = CBW20};
                if (!common::IsValidChan5Ghz(chan)) {
                    errorf("wlanmac band info for %u MHz has invalid channel %u\n",
                           supported_channels.base_freq, c);
                    errorf("wlanmac info: %s\n", debug::Describe(wlanmac_info).c_str());
                    return ZX_ERR_NOT_SUPPORTED;
                }
            }
            break;
        case common::kBaseFreq2Ghz:
            for (auto c : supported_channels.channels) {
                if (c == 0) {  // End of the valid channel
                    break;
                }
                auto chan = wlan_channel_t{.primary = c, .cbw = CBW20};
                if (!common::IsValidChan2Ghz(chan)) {
                    errorf("wlanmac band info for %u MHz has invalid cahnnel %u\n",
                           supported_channels.base_freq, c);
                    errorf("wlanmac info: %s\n", debug::Describe(wlanmac_info).c_str());
                    return ZX_ERR_NOT_SUPPORTED;
                }
            }
            break;
        default:
            errorf("wlanmac band info for %u MHz not supported\n", supported_channels.base_freq);
            errorf("wlanmac info: %s\n", debug::Describe(wlanmac_info).c_str());
            return ZX_ERR_NOT_SUPPORTED;
        }
    }
    // Add more sanity check here

    return ZX_OK;
}

bool Device::ShouldEnableMinstrel() {
    const auto& info = wlanmac_info_.ifc_info;
    return (info.driver_features & WLAN_DRIVER_FEATURE_TX_STATUS_REPORT) &&
           !(info.driver_features & WLAN_DRIVER_FEATURE_RATE_SELECTION);
}

zx_status_t Device::CreateMinstrel(uint32_t features) {
    debugfn();
    fbl::unique_ptr<Timer> timer;
    ObjectId timer_id;
    timer_id.set_subtype(to_enum_type(ObjectSubtype::kTimer));
    timer_id.set_target(to_enum_type(ObjectTarget::kMinstrel));
    auto status = GetTimer(ToPortKey(PortKeyType::kDevice, timer_id.val()), &timer);
    if (status != ZX_OK) {
        errorf("could not create minstrel timer: %d\n", status);
        return status;
    }
    const zx::duration minstrel_update_interval = (features & WLAN_DRIVER_FEATURE_SYNTH) != 0
                                                      ? kMinstrelUpdateIntervalForHwSim
                                                      : kMinstrelUpdateIntervalNormal;
    minstrel_.reset(new MinstrelRateSelector(std::move(timer), ProbeSequence::RandomSequence(),
                                             minstrel_update_interval));
    return ZX_OK;
}

void Device::AddMinstrelPeer(const wlan_assoc_ctx_t& assoc_ctx) {
    if (minstrel_ == nullptr) { return; }
    minstrel_->AddPeer(assoc_ctx);
}

}  // namespace wlan
