Coverage Report

Created: 2024-07-09 06:09

/proc/self/cwd/pw_bluetooth_hci/packet.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2021 The Pigweed Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4
// use this file except in compliance with the License. You may obtain a copy of
5
// the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
// License for the specific language governing permissions and limitations under
13
// the License.
14
#include "pw_bluetooth_hci/packet.h"
15
16
#include "pw_bytes/byte_builder.h"
17
#include "pw_bytes/endian.h"
18
#include "pw_status/try.h"
19
20
namespace pw::bluetooth_hci {
21
namespace {
22
23
using pw::bytes::ReadInOrder;
24
25
}  // namespace
26
27
Result<ConstByteSpan> CommandPacket::Encode(ByteSpan buffer,
28
0
                                            endian order) const {
29
0
  ByteBuilder builder(buffer);
30
0
  builder.PutUint16(opcode_, order);
31
0
  builder.PutUint8(parameters_.size_bytes());
32
0
  builder.append(parameters_);
33
0
  PW_TRY(builder.status());
34
0
  return ConstByteSpan(builder.data(), builder.size());
35
0
}
36
37
std::optional<CommandPacket> CommandPacket::Decode(ConstByteSpan data,
38
3.30k
                                                   endian order) {
39
3.30k
  if (data.size_bytes() < kHeaderSizeBytes) {
40
10
    return std::nullopt;  // Not enough data to parse the packet header.
41
10
  }
42
43
3.29k
  const uint8_t parameter_total_length =
44
3.29k
      static_cast<uint8_t>(data[kParameterTotalLengthByteOffset]);
45
3.29k
  if (data.size_bytes() < (kHeaderSizeBytes + parameter_total_length)) {
46
13
    return std::nullopt;  // Not enough data to cover the parameter bytes.
47
13
  }
48
49
3.28k
  const uint16_t opcode =
50
3.28k
      ReadInOrder<uint16_t>(order, &data[kOpcodeByteOffset]);
51
3.28k
  return CommandPacket(opcode,
52
3.28k
                       data.subspan(kHeaderSizeBytes, parameter_total_length));
53
3.29k
}
54
55
Result<ConstByteSpan> AsyncDataPacket::Encode(ByteSpan buffer,
56
0
                                              endian order) const {
57
0
  ByteBuilder builder(buffer);
58
0
  builder.PutUint16(handle_and_fragmentation_bits_, order);
59
0
  builder.PutUint16(data_.size_bytes(), order);
60
0
  builder.append(data_);
61
0
  PW_TRY(builder.status());
62
0
  return ConstByteSpan(builder.data(), builder.size());
63
0
}
64
65
std::optional<AsyncDataPacket> AsyncDataPacket::Decode(ConstByteSpan data,
66
2.07k
                                                       endian order) {
67
2.07k
  if (data.size_bytes() < kHeaderSizeBytes) {
68
10
    return std::nullopt;  // Not enough data to parse the packet header.
69
10
  }
70
71
2.06k
  const uint16_t data_total_length =
72
2.06k
      ReadInOrder<uint16_t>(order, &data[kDataTotalLengthByteOffset]);
73
2.06k
  if (data.size_bytes() < (kHeaderSizeBytes + data_total_length)) {
74
40
    return std::nullopt;  // Not enough data to cover the data bytes.
75
40
  }
76
77
2.02k
  const uint16_t handle_and_flag_bits = ReadInOrder<uint16_t>(
78
2.02k
      order, &data[kHandleAndFragmentationBitsByteOffset]);
79
2.02k
  return AsyncDataPacket(handle_and_flag_bits,
80
2.02k
                         data.subspan(kHeaderSizeBytes, data_total_length));
81
2.06k
}
82
83
Result<ConstByteSpan> SyncDataPacket::Encode(ByteSpan buffer,
84
0
                                             endian order) const {
85
0
  ByteBuilder builder(buffer);
86
0
  builder.PutUint16(handle_and_status_bits_, order);
87
0
  builder.PutUint8(data_.size_bytes());
88
0
  builder.append(data_);
89
0
  PW_TRY(builder.status());
90
0
  return ConstByteSpan(builder.data(), builder.size());
91
0
}
92
93
std::optional<SyncDataPacket> SyncDataPacket::Decode(ConstByteSpan data,
94
1.78k
                                                     endian order) {
95
1.78k
  if (data.size_bytes() < kHeaderSizeBytes) {
96
11
    return std::nullopt;  // Not enough data to parse the packet header.
97
11
  }
98
99
1.77k
  const uint8_t data_total_length =
100
1.77k
      static_cast<uint8_t>(data[kDataTotalLengthByteOffset]);
101
1.77k
  if (data.size_bytes() < (kHeaderSizeBytes + data_total_length)) {
102
14
    return std::nullopt;  // Not enough data to cover the data bytes.
103
14
  }
104
105
1.75k
  const uint16_t handle_and_status_bits =
106
1.75k
      ReadInOrder<uint16_t>(order, &data[kHandleAndStatusBitsByteOffset]);
107
1.75k
  return SyncDataPacket(handle_and_status_bits,
108
1.75k
                        data.subspan(kHeaderSizeBytes, data_total_length));
109
1.77k
}
110
111
0
Result<ConstByteSpan> EventPacket::Encode(ByteSpan buffer) const {
112
0
  ByteBuilder builder(buffer);
113
0
  builder.PutUint8(event_code_);
114
0
  builder.PutUint8(parameters_.size_bytes());
115
0
  builder.append(parameters_);
116
0
  PW_TRY(builder.status());
117
0
  return ConstByteSpan(builder.data(), builder.size());
118
0
}
119
120
2.18k
std::optional<EventPacket> EventPacket::Decode(ConstByteSpan data) {
121
2.18k
  if (data.size_bytes() < kHeaderSizeBytes) {
122
9
    return std::nullopt;  // Not enough data to parse the packet header.
123
9
  }
124
125
2.17k
  const uint8_t parameter_total_length =
126
2.17k
      static_cast<uint8_t>(data[kParameterTotalLengthByteOffset]);
127
2.17k
  if (data.size_bytes() < (kHeaderSizeBytes + parameter_total_length)) {
128
14
    return std::nullopt;  // Not enough data to cover the parameter bytes.
129
14
  }
130
131
2.15k
  const uint8_t event_code = static_cast<uint8_t>(data[kEventCodeByteOffset]);
132
2.15k
  return EventPacket(event_code,
133
2.15k
                     data.subspan(kHeaderSizeBytes, parameter_total_length));
134
2.17k
}
135
136
}  // namespace pw::bluetooth_hci