// Copyright 2019 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 "ot_radio.h"

#include <lib/async-loop/default.h>
#include <lib/async/cpp/task.h>
#include <lib/ddk/debug.h>
#include <lib/ddk/driver.h>
#include <lib/ddk/hw/reg.h>
#include <lib/ddk/metadata.h>
#include <lib/driver-unit-test/utils.h>
#include <lib/fidl/llcpp/server.h>
#include <lib/fit/defer.h>
#include <stdio.h>
#include <sys/types.h>
#include <zircon/compiler.h>
#include <zircon/status.h>
#include <zircon/time.h>

#include <iterator>

#include <ddktl/fidl.h>
#include <fbl/auto_lock.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>

#include "src/connectivity/openthread/drivers/ot-radio/ot_radio_bind.h"
#include "src/connectivity/openthread/drivers/ot-radio/ot_radio_bootloader.h"

namespace ot {
namespace lowpan_spinel_fidl = fuchsia_lowpan_spinel;

OtRadioDevice::LowpanSpinelDeviceFidlImpl::LowpanSpinelDeviceFidlImpl(OtRadioDevice& ot_radio)
    : ot_radio_obj_(ot_radio) {}

void OtRadioDevice::LowpanSpinelDeviceFidlImpl::Bind(
    async_dispatcher_t* dispatcher, fidl::ServerEnd<lowpan_spinel_fidl::Device> channel) {
  fidl::OnUnboundFn<LowpanSpinelDeviceFidlImpl> on_unbound =
      [](LowpanSpinelDeviceFidlImpl* server, fidl::UnbindInfo /*unused*/,
         fidl::ServerEnd<lowpan_spinel_fidl::Device> /*unused*/) {
        server->ot_radio_obj_.fidl_impl_obj_.release();
      };
  ot_radio_obj_.fidl_binding_ =
      fidl::BindServer(dispatcher, std::move(channel), this, std::move(on_unbound));
}

void OtRadioDevice::LowpanSpinelDeviceFidlImpl::Open(OpenCompleter::Sync& completer) {
  zx_status_t res = ot_radio_obj_.Reset();
  if (res == ZX_OK) {
    zxlogf(DEBUG, "open succeed, returning");
    ot_radio_obj_.power_status_ = OT_SPINEL_DEVICE_ON;
    (*ot_radio_obj_.fidl_binding_)->OnReadyForSendFrames(kOutboundAllowanceInit);
    ot_radio_obj_.inbound_allowance_ = 0;
    ot_radio_obj_.outbound_allowance_ = kOutboundAllowanceInit;
    ot_radio_obj_.inbound_cnt_ = 0;
    ot_radio_obj_.outbound_cnt_ = 0;
    completer.ReplySuccess();
  } else {
    zxlogf(ERROR, "Error in handling FIDL close req: %s, power status: %u",
           zx_status_get_string(res), ot_radio_obj_.power_status_);
    completer.ReplyError(lowpan_spinel_fidl::wire::Error::UNSPECIFIED);
  }
}

void OtRadioDevice::LowpanSpinelDeviceFidlImpl::Close(CloseCompleter::Sync& completer) {
  zx_status_t res = ot_radio_obj_.AssertResetPin();
  if (res == ZX_OK) {
    ot_radio_obj_.power_status_ = OT_SPINEL_DEVICE_OFF;
    completer.ReplySuccess();
  } else {
    zxlogf(ERROR, "Error in handling FIDL close req: %s, power status: %u",
           zx_status_get_string(res), ot_radio_obj_.power_status_);
    completer.ReplyError(lowpan_spinel_fidl::wire::Error::UNSPECIFIED);
  }
}

void OtRadioDevice::LowpanSpinelDeviceFidlImpl::GetMaxFrameSize(
    GetMaxFrameSizeCompleter::Sync& completer) {
  completer.Reply(kMaxFrameSize);
}

void OtRadioDevice::LowpanSpinelDeviceFidlImpl::SendFrame(::fidl::VectorView<uint8_t> data,
                                                          SendFrameCompleter::Sync& completer) {
  if (ot_radio_obj_.power_status_ == OT_SPINEL_DEVICE_OFF) {
    (*ot_radio_obj_.fidl_binding_)->OnError(lowpan_spinel_fidl::wire::Error::CLOSED, false);
  } else if (data.count() > kMaxFrameSize) {
    (*ot_radio_obj_.fidl_binding_)
        ->OnError(lowpan_spinel_fidl::wire::Error::OUTBOUND_FRAME_TOO_LARGE, false);
  } else if (ot_radio_obj_.outbound_allowance_ == 0) {
    // Client violates the protocol, close FIDL channel and device. Will not send OnError event.
    ot_radio_obj_.power_status_ = OT_SPINEL_DEVICE_OFF;
    ot_radio_obj_.AssertResetPin();
    ot_radio_obj_.fidl_binding_->Close(ZX_ERR_IO_OVERRUN);
    completer.Close(ZX_ERR_IO_OVERRUN);
  } else {
    // All good, send out the frame.
    zx_status_t res = ot_radio_obj_.RadioPacketTx(data.begin(), data.count());
    if (res != ZX_OK) {
      zxlogf(ERROR, "Error in handling send frame req: %s", zx_status_get_string(res));
    } else {
      ot_radio_obj_.outbound_allowance_--;
      ot_radio_obj_.outbound_cnt_++;
      zxlogf(DEBUG, "Successfully Txed pkt, total tx pkt %lu", ot_radio_obj_.outbound_cnt_);
      if ((ot_radio_obj_.outbound_cnt_ & 1) == 0) {
        (*ot_radio_obj_.fidl_binding_)->OnReadyForSendFrames(kOutboundAllowanceInc);
        ot_radio_obj_.outbound_allowance_ += kOutboundAllowanceInc;
      }
    }
  }
}

void OtRadioDevice::LowpanSpinelDeviceFidlImpl::ReadyToReceiveFrames(
    uint32_t number_of_frames, ReadyToReceiveFramesCompleter::Sync& completer) {
  zxlogf(DEBUG, "ot-radio: allow to receive %u frame", number_of_frames);
  ot_radio_obj_.inbound_allowance_ += number_of_frames;
  if (ot_radio_obj_.inbound_allowance_ > 0 && ot_radio_obj_.spinel_framer_.get()) {
    ot_radio_obj_.spinel_framer_->SetInboundAllowanceStatus(true);
    if (ot_radio_obj_.interrupt_is_asserted_) {
      // signal the event loop thread to handle interrupt
      ot_radio_obj_.InvokeInterruptHandler();
    }
    ot_radio_obj_.ReadRadioPacket();
  }
}

OtRadioDevice::OtRadioDevice(zx_device_t* device)
    : ddk::Device<OtRadioDevice, ddk::Unbindable, ddk::Messageable>(device),
      loop_(&kAsyncLoopConfigNoAttachToCurrentThread) {}

zx_status_t OtRadioDevice::DdkMessage(fidl_incoming_msg_t* msg, fidl_txn_t* txn) {
  DdkTransaction transaction(txn);
  fidl::WireDispatch<lowpan_spinel_fidl::DeviceSetup>(this, msg, &transaction);
  return transaction.Status();
}

void OtRadioDevice::SetChannel(fidl::ServerEnd<fuchsia_lowpan_spinel::Device> request,
                               SetChannelCompleter::Sync& completer) {
  if (fidl_impl_obj_ != nullptr) {
    zxlogf(ERROR, "ot-radio: channel already set");
    completer.ReplyError(ZX_ERR_ALREADY_BOUND);
    return;
  }
  if (!request.is_valid()) {
    completer.ReplyError(ZX_ERR_BAD_HANDLE);
    return;
  }
  fidl_impl_obj_ = std::make_unique<LowpanSpinelDeviceFidlImpl>(*this);
  fidl_impl_obj_->Bind(loop_.dispatcher(), std::move(request));
  completer.ReplySuccess();
}

zx_status_t OtRadioDevice::StartLoopThread() {
  zxlogf(DEBUG, "Start loop thread");
  zx_status_t status = loop_.StartThread("ot-stack-loop");
  if (status == ZX_OK) {
    thrd_status_.loop_thrd_running = true;
  }
  return status;
}

bool OtRadioDevice::RunUnitTests(void* ctx, zx_device_t* parent, zx_handle_t channel) {
  return driver_unit_test::RunZxTests("OtRadioTests", parent, channel);
}

zx_status_t OtRadioDevice::Init() {
  spi_ = ddk::SpiProtocolClient(parent(), "spi");
  if (!spi_.is_valid()) {
    zxlogf(ERROR, "ot-radio %s: failed to acquire spi", __func__);
    return ZX_ERR_NOT_SUPPORTED;
  }

  gpio_[OT_RADIO_INT_PIN] = ddk::GpioProtocolClient(parent(), "gpio-int");
  if (!gpio_[OT_RADIO_INT_PIN].is_valid()) {
    zxlogf(ERROR, "ot-radio %s: failed to acquire interrupt gpio", __func__);
    return ZX_ERR_NO_RESOURCES;
  }

  zx_status_t status = gpio_[OT_RADIO_INT_PIN].ConfigIn(GPIO_NO_PULL);

  if (status != ZX_OK) {
    zxlogf(ERROR, "ot-radio %s: failed to configure interrupt gpio", __func__);
    return status;
  }

  status = gpio_[OT_RADIO_INT_PIN].GetInterrupt(ZX_INTERRUPT_MODE_EDGE_LOW, &interrupt_);

  if (status != ZX_OK) {
    zxlogf(ERROR, "ot-radio %s: failed to get interrupt", __func__);
    return status;
  }

  gpio_[OT_RADIO_RESET_PIN] = ddk::GpioProtocolClient(parent(), "gpio-reset");
  if (!gpio_[OT_RADIO_RESET_PIN].is_valid()) {
    zxlogf(ERROR, "ot-radio %s: failed to acquire reset gpio", __func__);
    return ZX_ERR_NO_RESOURCES;
  }

  status = gpio_[OT_RADIO_RESET_PIN].ConfigOut(1);

  if (status != ZX_OK) {
    zxlogf(ERROR, "ot-radio %s: failed to configure rst gpio, status = %d", __func__, status);
    return status;
  }

  gpio_[OT_RADIO_BOOTLOADER_PIN] = ddk::GpioProtocolClient(parent(), "gpio-bootloader");
  if (!gpio_[OT_RADIO_BOOTLOADER_PIN].is_valid()) {
    zxlogf(ERROR, "ot-radio %s: failed to acquire radio bootloader pin", __func__);
    return ZX_ERR_NO_RESOURCES;
  }

  status = gpio_[OT_RADIO_BOOTLOADER_PIN].ConfigOut(1);

  if (status != ZX_OK) {
    zxlogf(ERROR, "ot-radio %s: failed to configure bootloader gpio, status = %d", __func__,
           status);
    return status;
  }

  zx_device_t* pdev_fragment = nullptr;
  bool found =
      device_get_fragment(parent(), "fuchsia.hardware.platform.device.PDev", &pdev_fragment);
  if (!found) {
    zxlogf(ERROR, "ot-radio %s: failed to acquire pdev fragment", __func__);
    return ZX_ERR_NO_RESOURCES;
  }

  size_t actual;
  uint32_t device_id;
  status = device_get_metadata(pdev_fragment, DEVICE_METADATA_PRIVATE, &device_id,
                               sizeof(device_id), &actual);
  if (status != ZX_OK || sizeof(device_id) != actual) {
    zxlogf(ERROR, "ot-radio: failed to read metadata");
    return status == ZX_OK ? ZX_ERR_INTERNAL : status;
  }

  spinel_framer_ = std::make_unique<ot::SpinelFramer>();
  spinel_framer_->Init(spi_);

  return ZX_OK;
}

zx_status_t OtRadioDevice::ReadRadioPacket() {
  if ((inbound_allowance_ > 0) && (spinel_framer_->IsPacketPresent())) {
    spinel_framer_->ReceivePacketFromRadio(spi_rx_buffer_, &spi_rx_buffer_len_);
    if (spi_rx_buffer_len_ > 0) {
      if (thrd_status_.loop_thrd_running) {
        async::PostTask(loop_.dispatcher(), [this, pkt = std::move(spi_rx_buffer_),
                                             len = std::move(spi_rx_buffer_len_)]() {
          this->HandleRadioRxFrame(pkt, len);
        });
      } else {
        // Loop thread is not running, this is one off case to be handled
        // Results either when running test or getting NCP version
        inbound_allowance_ = 0;
        spinel_framer_->SetInboundAllowanceStatus(false);
      }

      // Signal to driver test, waiting for a response
      sync_completion_signal(&spi_rx_complete_);
    }
  }
  return ZX_OK;
}

zx_status_t OtRadioDevice::HandleRadioRxFrame(uint8_t* frameBuffer, uint16_t length) {
  zxlogf(DEBUG, "ot-radio: received frame of len:%d", length);
  if (power_status_ == OT_SPINEL_DEVICE_ON) {
    auto data = fidl::VectorView<uint8_t>::FromExternal(frameBuffer, length);
    zx_status_t res = (*fidl_binding_)->OnReceiveFrame(std::move(data));
    if (res != ZX_OK) {
      zxlogf(ERROR, "ot-radio: failed to send OnReceive() event due to %s",
             zx_status_get_string(res));
    }
    inbound_allowance_--;
    inbound_cnt_++;
    if ((inbound_allowance_ == 0) && spinel_framer_.get()) {
      spinel_framer_->SetInboundAllowanceStatus(false);
    }
  } else {
    zxlogf(ERROR, "OtRadioDevice::HandleRadioRxFrame(): Radio is off");
  }
  return ZX_OK;
}

zx_status_t OtRadioDevice::RadioPacketTx(uint8_t* frameBuffer, uint16_t length) {
  zxlogf(DEBUG, "ot-radio: RadioPacketTx");
  zx_port_packet packet = {PORT_KEY_TX_TO_RADIO, ZX_PKT_TYPE_USER, ZX_OK, {}};
  if (!port_.is_valid()) {
    return ZX_ERR_BAD_STATE;
  }
  memcpy(spi_tx_buffer_, frameBuffer, length);
  spi_tx_buffer_len_ = length;
  return port_.queue(&packet);
}

zx_status_t OtRadioDevice::InvokeInterruptHandler() {
  zxlogf(DEBUG, "ot-radio: InvokeInterruptHandler");
  zx_port_packet packet = {PORT_KEY_RADIO_IRQ, ZX_PKT_TYPE_USER, ZX_OK, {}};
  if (!port_.is_valid()) {
    return ZX_ERR_BAD_STATE;
  }
  return port_.queue(&packet);
}

bool OtRadioDevice::IsInterruptAsserted() {
  uint8_t pin_level = 0;
  gpio_[OT_RADIO_INT_PIN].Read(&pin_level);
  return pin_level == 0;
}

zx_status_t OtRadioDevice::DriverUnitTestGetNCPVersion() { return GetNCPVersion(); }

zx_status_t OtRadioDevice::GetNCPVersion() {
  spinel_framer_->SetInboundAllowanceStatus(true);
  inbound_allowance_ = kOutboundAllowanceInit;
  uint8_t get_ncp_version_cmd[] = {0x80, 0x02, 0x02};  // HEADER, CMD ID, PROPERTY ID
  // populate TID (lower 4 bits in header)
  get_ncp_version_cmd[0] = (get_ncp_version_cmd[0] & 0xf0) | (kGetNcpVersionTID & 0x0f);
  return RadioPacketTx(get_ncp_version_cmd, sizeof(get_ncp_version_cmd));
}

zx_status_t OtRadioDevice::DriverUnitTestGetResetEvent() {
  spinel_framer_->SetInboundAllowanceStatus(true);
  inbound_allowance_ = kOutboundAllowanceInit;
  return Reset();
}

zx_status_t OtRadioDevice::AssertResetPin() {
  zx_status_t status = ZX_OK;
  zxlogf(DEBUG, "ot-radio: assert reset pin");

  status = gpio_[OT_RADIO_RESET_PIN].Write(0);
  if (status != ZX_OK) {
    zxlogf(ERROR, "ot-radio: gpio write failed");
    return status;
  }
  zx::nanosleep(zx::deadline_after(zx::msec(100)));
  return status;
}

zx_status_t OtRadioDevice::Reset() {
  zx_status_t status = ZX_OK;
  zxlogf(DEBUG, "ot-radio: reset");

  status = gpio_[OT_RADIO_RESET_PIN].Write(0);
  if (status != ZX_OK) {
    zxlogf(ERROR, "ot-radio: gpio write failed");
    return status;
  }
  zx::nanosleep(zx::deadline_after(zx::msec(100)));

  status = gpio_[OT_RADIO_RESET_PIN].Write(1);
  if (status != ZX_OK) {
    zxlogf(ERROR, "ot-radio: gpio write failed");
    return status;
  }
  zx::nanosleep(zx::deadline_after(zx::msec(400)));
  return status;
}

zx_status_t OtRadioDevice::RadioThread() {
  zx_status_t status = ZX_OK;
  zxlogf(INFO, "ot-radio: entered thread");

  while (true) {
    zx_port_packet_t packet = {};
    int timeout_ms = spinel_framer_->GetTimeoutMs();
    auto status = port_.wait(zx::deadline_after(zx::msec(timeout_ms)), &packet);

    if (status == ZX_ERR_TIMED_OUT) {
      spinel_framer_->TrySpiTransaction();
      ReadRadioPacket();
      continue;
    } else if (status != ZX_OK) {
      zxlogf(ERROR, "ot-radio: port wait failed: %d", status);
      return thrd_error;
    }

    if (packet.key == PORT_KEY_EXIT_THREAD) {
      break;
    } else if (packet.key == PORT_KEY_RADIO_IRQ) {
      interrupt_.ack();
      zxlogf(DEBUG, "ot-radio: interrupt");
      do {
        spinel_framer_->HandleInterrupt();
        ReadRadioPacket();

        interrupt_is_asserted_ = IsInterruptAsserted();
      } while (interrupt_is_asserted_ && inbound_allowance_ != 0);
    } else if (packet.key == PORT_KEY_TX_TO_RADIO) {
      spinel_framer_->SendPacketToRadio(spi_tx_buffer_, spi_tx_buffer_len_);
    }
  }
  zxlogf(DEBUG, "ot-radio: exiting");

  return status;
}

zx_status_t OtRadioDevice::CreateBindAndStart(void* ctx, zx_device_t* parent) {
  std::unique_ptr<OtRadioDevice> ot_radio_dev;
  zx_status_t status = Create(ctx, parent, &ot_radio_dev);
  if (status != ZX_OK) {
    return status;
  }

  status = ot_radio_dev->Bind();
  if (status != ZX_OK) {
    return status;
  }
  // device intentionally leaked as it is now held by DevMgr
  auto dev_ptr = ot_radio_dev.release();

  status = dev_ptr->Start();
  if (status != ZX_OK) {
    return status;
  }

  return status;
}

zx_status_t OtRadioDevice::Create(void* ctx, zx_device_t* parent,
                                  std::unique_ptr<OtRadioDevice>* out) {
  auto dev = std::make_unique<OtRadioDevice>(parent);
  zx_status_t status = dev->Init();

  if (status != ZX_OK) {
    zxlogf(ERROR, "ot-radio: Driver init failed %d", status);
    return status;
  }

  *out = std::move(dev);

  return ZX_OK;
}

zx_status_t OtRadioDevice::Bind() {
  zx_status_t status = DdkAdd(ddk::DeviceAddArgs("ot-radio").set_proto_id(ZX_PROTOCOL_OT_RADIO));
  if (status != ZX_OK) {
    zxlogf(ERROR, "ot-radio: Could not create device: %d", status);
    return status;
  } else {
    zxlogf(DEBUG, "ot-radio: Added device");
  }
  return status;
}

zx_status_t OtRadioDevice::CreateAndBindPortToIntr() {
  zx_status_t status = zx::port::create(ZX_PORT_BIND_TO_INTERRUPT, &port_);
  if (status != ZX_OK) {
    zxlogf(ERROR, "ot-radio: port create failed %d", status);
    return status;
  }

  status = interrupt_.bind(port_, PORT_KEY_RADIO_IRQ, 0);
  if (status != ZX_OK) {
    zxlogf(ERROR, "ot-radio: interrupt bind failed %d", status);
    return status;
  }

  return ZX_OK;
}

void OtRadioDevice::StartRadioThread() {
  auto callback = [](void* cookie) {
    return reinterpret_cast<OtRadioDevice*>(cookie)->RadioThread();
  };
  int ret = thrd_create_with_name(&thread_, callback, this, "ot-radio-thread");
  ZX_DEBUG_ASSERT(ret == thrd_success);

  // Set status flag so shutdown can take appropriate action
  // cleared by StopRadioThread
  thrd_status_.radio_thrd_running = true;
}

zx_status_t OtRadioDevice::Start() {
  zx_status_t status = CreateAndBindPortToIntr();
  if (status != ZX_OK) {
    return status;
  }

  StartRadioThread();
  auto cleanup = fit::defer([&]() { ShutDown(); });

#ifdef INTERNAL_ACCESS
  // Update the NCP Firmware if new version is available
  bool update_fw = false;
  status = CheckFWUpdateRequired(&update_fw);
  if (status != ZX_OK) {
    zxlogf(ERROR, "ot-radio: CheckFWUpdateRequired failed with status: %d", status);
    return status;
  }

  if (update_fw) {
    // Print as it may be useful, expected to be rare occurrence,
    zxlogf(INFO, "ot-radio: Will start FW update");

    // Stop the loop for handling port events, so port can be used by bootloader
    StopRadioThread();

    // Update firmware here
    OtRadioDeviceBootloader dev_bl(this);
    OtRadioBlResult result = dev_bl.UpdateRadioFirmware();
    if (result != BL_RET_SUCCESS) {
      zxlogf(ERROR, "ot-radio: radio firmware update failed with %d. Last zx_status %d", result,
             dev_bl.GetLastZxStatus());
      return ZX_ERR_INTERNAL;
    }

    zxlogf(INFO, "ot-radio: FW update done successfully");

    // Restart the Radio thread:
    StartRadioThread();
  } else {
    zxlogf(DEBUG, "ot-radio: NCP firmware is already up-to-date");
  }
#endif

  status = StartLoopThread();
  if (status != ZX_OK) {
    zxlogf(ERROR, "ot-radio: Could not start loop thread");
    return status;
  }

  zxlogf(DEBUG, "ot-radio: Started thread");

  cleanup.cancel();

  return status;
}

#ifdef INTERNAL_ACCESS
zx_status_t OtRadioDevice::CheckFWUpdateRequired(bool* update_fw) {
  *update_fw = false;

  // Get the new firmware version:
  std::string new_fw_version = GetNewFirmwareVersion();
  if (new_fw_version.size() == 0) {
    // Invalid version string indicates invalid firmware
    zxlogf(ERROR, "ot-radio: The new firmware is invalid");
    *update_fw = false;
    // Return error instead of ZX_OK and just not-updating,
    // may point to some bug
    return ZX_ERR_NO_RESOURCES;
  }

  int attempts;
  bool response_received = false;

  // Now get the ncp version
  auto status = GetNCPVersion();
  if (status != ZX_OK) {
    zxlogf(ERROR, "ot-radio: get ncp version failed with status: %d", status);
    return status;
  }

  for (attempts = 0; attempts < kGetNcpVersionMaxRetries; attempts++) {
    zxlogf(DEBUG, "ot-radio: waiting for response for GetNCPVersion cmd, attempt: %d / %d",
           attempts + 1, kGetNcpVersionMaxRetries);

    // Simply update the allowance for each attempt. Radio will send
    // response to GetNCPVersion to us eventually. Ignore any response to
    // earlier commands.
    spinel_framer_->SetInboundAllowanceStatus(true);
    inbound_allowance_ = kOutboundAllowanceInit;

    // Wait for response to arrive, signaled by spi_rx_complete_
    status = sync_completion_wait(&spi_rx_complete_, ZX_SEC(10));
    sync_completion_reset(&spi_rx_complete_);
    if (status != ZX_OK) {
      zxlogf(ERROR,
             "ot-radio: sync_completion_wait failed with status: %d, \
         this means firmware may be behaving incorrectly\n",
             status);
      // We want to update fw in this case
      *update_fw = true;
      return ZX_OK;
    }

    // Check for matching TID in spinel header
    if ((spi_rx_buffer_[0] & 0xf) == kGetNcpVersionTID) {
      response_received = true;
      break;
    }
  }

  if (!response_received) {
    zxlogf(ERROR, "ot-radio: no matching response is received for get ncp version command.");
    zxlogf(ERROR, "ot-radio: updating the the firmware");
    // This can again mean bad firmware, so update the firmware:
    *update_fw = true;
    return ZX_OK;
  }

  // Response is received, copy it to the string cur_fw_version
  // First make sure that last character is null
  ZX_DEBUG_ASSERT(spi_rx_buffer_len_ <= kMaxFrameSize);
  spi_rx_buffer_[spi_rx_buffer_len_ - 1] = '\0';
  zxlogf(DEBUG, "ot-radio: response received size = %d, value : %s", spi_rx_buffer_len_,
         reinterpret_cast<char*>(&(spi_rx_buffer_[3])));
  std::string cur_fw_version;
  cur_fw_version.assign(reinterpret_cast<char*>(&(spi_rx_buffer_[3])));

  // We want to update firmware if the versions don't match
  *update_fw = (cur_fw_version.compare(new_fw_version) != 0);
  if (*update_fw) {
    zxlogf(INFO, "ot-radio: cur_fw_version: %s, new_fw_version: %s", cur_fw_version.c_str(),
           new_fw_version.c_str());
  }
  return ZX_OK;
}
#endif

void OtRadioDevice::DdkRelease() { delete this; }

void OtRadioDevice::DdkUnbind(ddk::UnbindTxn txn) {
  ShutDown();
  txn.Reply();
}

void OtRadioDevice::StopRadioThread() {
  if (thrd_status_.radio_thrd_running) {
    zx_port_packet packet = {PORT_KEY_EXIT_THREAD, ZX_PKT_TYPE_USER, ZX_OK, {}};
    port_.queue(&packet);
    thrd_join(thread_, NULL);
    thrd_status_.radio_thrd_running = false;
  }
}

void OtRadioDevice::StopLoopThread() {
  if (thrd_status_.loop_thrd_running) {
    loop_.Shutdown();
    thrd_status_.loop_thrd_running = false;
  }
}

zx_status_t OtRadioDevice::ShutDown() {
  StopRadioThread();

  gpio_[OT_RADIO_INT_PIN].ReleaseInterrupt();
  interrupt_.destroy();

  StopLoopThread();

  return ZX_OK;
}

static constexpr zx_driver_ops_t driver_ops = []() {
  zx_driver_ops_t ops = {};
  ops.version = DRIVER_OPS_VERSION;
  ops.bind = OtRadioDevice::CreateBindAndStart;
  ops.run_unit_tests = OtRadioDevice::RunUnitTests;
  return ops;
}();

}  // namespace ot

ZIRCON_DRIVER(ot, ot::driver_ops, "ot_radio", "0.1");
