blob: 659d45e8623c541e943fe5045bfc7e62e70ebf0f [file] [log] [blame]
// 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 "spi-child.h"
#include <ddktl/fidl.h>
#include <fbl/vector.h>
#include "spi.h"
namespace spi {
namespace sharedmemory = fuchsia_hardware_sharedmemory;
void SpiChild::TransmitVector(::fidl::VectorView<uint8_t> data,
TransmitVectorCompleter::Sync& completer) {
size_t rx_actual;
zx_status_t status = spi_.Exchange(cs_, data.data(), data.count(), nullptr, 0, &rx_actual);
if (status == ZX_OK) {
completer.Reply(ZX_OK);
} else {
completer.Reply(status);
}
}
void SpiChild::ReceiveVector(uint32_t size, ReceiveVectorCompleter::Sync& completer) {
fbl::Vector<uint8_t> rxdata;
rxdata.reserve(size);
size_t rx_actual;
zx_status_t status = spi_.Exchange(cs_, nullptr, 0, rxdata.begin(), size, &rx_actual);
if (status == ZX_OK && rx_actual == size) {
auto rx_vector = fidl::VectorView<uint8_t>::FromExternal(rxdata.data(), size);
completer.Reply(ZX_OK, std::move(rx_vector));
} else {
completer.Reply(status == ZX_OK ? ZX_ERR_INTERNAL : status, fidl::VectorView<uint8_t>());
}
}
void SpiChild::ExchangeVector(::fidl::VectorView<uint8_t> txdata,
ExchangeVectorCompleter::Sync& completer) {
fbl::Vector<uint8_t> rxdata;
const size_t size = txdata.count();
rxdata.reserve(size);
size_t rx_actual;
zx_status_t status = spi_.Exchange(cs_, txdata.data(), size, rxdata.begin(), size, &rx_actual);
if (status == ZX_OK && rx_actual == size) {
auto rx_vector = fidl::VectorView<uint8_t>::FromExternal(rxdata.data(), size);
completer.Reply(ZX_OK, std::move(rx_vector));
} else {
completer.Reply(status == ZX_OK ? ZX_ERR_INTERNAL : status, fidl::VectorView<uint8_t>());
}
}
void SpiChild::RegisterVmo(uint32_t vmo_id, fuchsia_mem::wire::Range vmo,
sharedmemory::wire::SharedVmoRight rights,
RegisterVmoCompleter::Sync& completer) {
sharedmemory::wire::SharedVmoRegister_RegisterVmo_Result result;
sharedmemory::wire::SharedVmoRegister_RegisterVmo_Response response = {};
zx_status_t status = spi_.RegisterVmo(cs_, vmo_id, std::move(vmo.vmo), vmo.offset, vmo.size,
static_cast<uint32_t>(rights));
if (status == ZX_OK) {
result.set_response(
fidl::ObjectView<sharedmemory::wire::SharedVmoRegister_RegisterVmo_Response>::FromExternal(
&response));
} else {
result.set_err(fidl::ObjectView<zx_status_t>::FromExternal(&status));
}
completer.Reply(std::move(result));
}
void SpiChild::UnregisterVmo(uint32_t vmo_id, UnregisterVmoCompleter::Sync& completer) {
sharedmemory::wire::SharedVmoRegister_UnregisterVmo_Result result;
sharedmemory::wire::SharedVmoRegister_UnregisterVmo_Response response = {};
zx_status_t status = spi_.UnregisterVmo(cs_, vmo_id, &response.vmo);
if (status == ZX_OK) {
result.set_response(
fidl::ObjectView<
sharedmemory::wire::SharedVmoRegister_UnregisterVmo_Response>::FromExternal(&response));
} else {
result.set_err(fidl::ObjectView<zx_status_t>::FromExternal(&status));
}
completer.Reply(std::move(result));
}
void SpiChild::Transmit(sharedmemory::wire::SharedVmoBuffer buffer,
TransmitCompleter::Sync& completer) {
sharedmemory::wire::SharedVmoIo_Transmit_Result result;
sharedmemory::wire::SharedVmoIo_Transmit_Response response = {};
zx_status_t status = spi_.TransmitVmo(cs_, buffer.vmo_id, buffer.offset, buffer.size);
if (status == ZX_OK) {
result.set_response(
fidl::ObjectView<sharedmemory::wire::SharedVmoIo_Transmit_Response>::FromExternal(
&response));
} else {
result.set_err(fidl::ObjectView<zx_status_t>::FromExternal(&status));
}
completer.Reply(std::move(result));
}
void SpiChild::Receive(sharedmemory::wire::SharedVmoBuffer buffer,
ReceiveCompleter::Sync& completer) {
sharedmemory::wire::SharedVmoIo_Receive_Result result;
sharedmemory::wire::SharedVmoIo_Receive_Response response = {};
zx_status_t status = spi_.ReceiveVmo(cs_, buffer.vmo_id, buffer.offset, buffer.size);
if (status == ZX_OK) {
result.set_response(
fidl::ObjectView<sharedmemory::wire::SharedVmoIo_Receive_Response>::FromExternal(
&response));
} else {
result.set_err(fidl::ObjectView<zx_status_t>::FromExternal(&status));
}
completer.Reply(std::move(result));
}
void SpiChild::Exchange(sharedmemory::wire::SharedVmoBuffer tx_buffer,
sharedmemory::wire::SharedVmoBuffer rx_buffer,
ExchangeCompleter::Sync& completer) {
sharedmemory::wire::SharedVmoIo_Exchange_Result result;
sharedmemory::wire::SharedVmoIo_Exchange_Response response = {};
zx_status_t status;
if (tx_buffer.size != rx_buffer.size) {
status = ZX_ERR_INVALID_ARGS;
} else {
status = spi_.ExchangeVmo(cs_, tx_buffer.vmo_id, tx_buffer.offset, rx_buffer.vmo_id,
rx_buffer.offset, tx_buffer.size);
}
if (status == ZX_OK) {
result.set_response(
fidl::ObjectView<sharedmemory::wire::SharedVmoIo_Exchange_Response>::FromExternal(
&response));
} else {
result.set_err(fidl::ObjectView<zx_status_t>::FromExternal(&status));
}
completer.Reply(std::move(result));
}
zx_status_t SpiChild::DdkMessage(fidl_incoming_msg_t* msg, fidl_txn_t* txn) {
DdkTransaction transaction(txn);
fidl::WireDispatch<fuchsia_hardware_spi::Device>(this, msg, &transaction);
return transaction.Status();
}
zx_status_t SpiChild::SpiTransmit(const uint8_t* txdata_list, size_t txdata_count) {
size_t actual;
spi_.Exchange(cs_, txdata_list, txdata_count, nullptr, 0, &actual);
return ZX_OK;
}
zx_status_t SpiChild::SpiReceive(uint32_t size, uint8_t* out_rxdata_list, size_t rxdata_count,
size_t* out_rxdata_actual) {
spi_.Exchange(cs_, nullptr, 0, out_rxdata_list, rxdata_count, out_rxdata_actual);
return ZX_OK;
}
zx_status_t SpiChild::SpiExchange(const uint8_t* txdata_list, size_t txdata_count,
uint8_t* out_rxdata_list, size_t rxdata_count,
size_t* out_rxdata_actual) {
spi_.Exchange(cs_, txdata_list, txdata_count, out_rxdata_list, rxdata_count, out_rxdata_actual);
return ZX_OK;
}
void SpiChild::SpiConnectServer(zx::channel server) {
spi_parent_.ConnectServer(std::move(server), this);
}
void SpiChild::DdkUnbind(ddk::UnbindTxn txn) { txn.Reply(); }
void SpiChild::DdkRelease() { __UNUSED bool dummy = Release(); }
} // namespace spi