blob: 0e4f67f8d93bce8526f848c3e613b71fae65ba3b [file] [log] [blame]
// Copyright 2018 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 <wlan/common/write_element.h>
namespace wlan {
namespace common {
namespace {
template<typename T>
struct PartTraits {
static constexpr size_t size_bytes(const T& t) {
return sizeof(T);
}
static void write(BufferWriter* w, const T& t) {
w->Write(as_bytes(Span<const T>{&t, 1u}));
}
};
template<typename T>
struct PartTraits<Span<T>> {
static constexpr size_t size_bytes(const Span<T>& t) {
return t.size_bytes();
}
static void write(BufferWriter* w, const Span<T>& t) {
w->Write(as_bytes(t));
}
};
template<size_t PadTo, typename... T>
void WriteWithPadding(BufferWriter* w, element_id::ElementId elem_id, const T&... parts) {
w->WriteByte(elem_id);
size_t total_size = (PartTraits<T>::size_bytes(parts) + ...);
size_t unpadded = total_size % PadTo;
size_t padding = 0;
if (unpadded > 0) {
padding = PadTo - unpadded;
}
w->WriteByte(static_cast<uint8_t>(total_size + padding));
(PartTraits<T>::write(w, parts) , ...);
for (size_t i = 0; i < padding; ++i) {
w->WriteByte(0);
}
}
template<typename... T>
void Write(BufferWriter* w, element_id::ElementId elem_id, const T&... parts) {
WriteWithPadding<1>(w, elem_id, parts...);
}
} // namespace
void WriteSsid(BufferWriter* w, Span<const uint8_t> ssid) {
Write(w, element_id::kSsid, ssid);
}
void WriteSupportedRates(BufferWriter* w, Span<const SupportedRate> supported_rates) {
Write(w, element_id::kSuppRates, supported_rates);
}
void WriteDsssParamSet(BufferWriter* w, uint8_t current_chan) {
Write(w, element_id::kDsssParamSet, current_chan);
}
void WriteCfParamSet(BufferWriter* w, CfParamSet param_set) {
Write(w, element_id::kCfParamSet, param_set);
}
void WriteTim(BufferWriter* w, TimHeader header, Span<const uint8_t> bitmap) {
Write(w, element_id::kTim, header, bitmap);
}
void WriteCountry(BufferWriter* w, Country country, Span<SubbandTriplet> triplets) {
WriteWithPadding<2>(w, element_id::kCountry, country, triplets);
}
void WriteExtendedSupportedRates(BufferWriter* w, Span<const SupportedRate> ext_supported_rates) {
Write(w, element_id::kExtSuppRates, ext_supported_rates);
}
void WriteMeshConfiguration(BufferWriter* w, MeshConfiguration mesh_config) {
Write(w, element_id::kMeshConfiguration, mesh_config);
}
void WriteMeshId(BufferWriter* w, Span<const uint8_t> mesh_id) {
Write(w, element_id::kMeshId, mesh_id);
}
void WriteQosCapability(BufferWriter* w, QosInfo qos_info) {
Write(w, element_id::kQosCapability, qos_info);
}
void WriteGcrGroupAddress(BufferWriter* w, common::MacAddr gcr_group_addr) {
Write(w, element_id::kGcrGroupAddress, gcr_group_addr);
}
void WriteHtCapabilities(BufferWriter* w, const HtCapabilities& ht_caps) {
Write(w, element_id::kHtCapabilities, ht_caps);
}
void WriteHtOperation(BufferWriter* w, const HtOperation& ht_op) {
Write(w, element_id::kHtOperation, ht_op);
}
void WriteVhtCapabilities(BufferWriter* w, const VhtCapabilities& vht_caps) {
Write(w, element_id::kVhtCapabilities, vht_caps);
}
void WriteVhtOperation(BufferWriter* w, const VhtOperation& vht_op) {
Write(w, element_id::kVhtOperation, vht_op);
}
void WriteMpmOpen(BufferWriter* w, MpmHeader mpm_header, const MpmPmk* pmk) {
auto pmk_bytes = pmk == nullptr ? Span<const uint8_t>{} : Span<const uint8_t>{pmk->data};
Write(w, element_id::kMeshPeeringManagement, mpm_header, pmk_bytes);
}
void WriteMpmConfirm(BufferWriter* w, MpmHeader mpm_header, uint16_t peer_link_id,
const MpmPmk* pmk) {
auto pmk_bytes = pmk == nullptr ? Span<const uint8_t>{} : Span<const uint8_t>{pmk->data};
Write(w, element_id::kMeshPeeringManagement, mpm_header, peer_link_id, pmk_bytes);
}
void WritePreq(BufferWriter* w, const PreqHeader& header,
const common::MacAddr* originator_external_addr,
const PreqMiddle& middle, Span<const PreqPerTarget> per_target) {
auto ext_bytes = originator_external_addr == nullptr
? Span<const uint8_t>{}
: Span<const uint8_t>{originator_external_addr->byte};
Write(w, element_id::kPreq, header, ext_bytes, middle, per_target);
}
void WritePrep(BufferWriter* w, const PrepHeader& header,
const common::MacAddr* target_external_addr, const PrepTail& tail) {
auto ext_bytes = target_external_addr == nullptr
? Span<const uint8_t>{}
: Span<const uint8_t>{target_external_addr->byte};
Write(w, element_id::kPrep, header, ext_bytes, tail);
}
} // namespace common
} // namespace wlan