Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c76a0bdf authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I321e12bf,If7e6e586,Ie145d1dd

* changes:
  l2cap: Add FCS support
  packet/parser: Add tests for payload size modifier
  packet/parser: Add Checksum support
parents 484de62b e6f7c92a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2,5 +2,6 @@ filegroup {
    name: "BluetoothL2capTestSources",
    srcs: [
        "l2cap_packet_test.cc",
        "fcs.cc",
    ],
}

system/gd/l2cap/fcs.cc

0 → 100644
+60 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "l2cap/fcs.h"

namespace {
// Table for optimizing the CRC calculation, which is a bitwise operation.
static const uint16_t crctab[256] = {
    0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1,
    0xc481, 0x0440, 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40,
    0xc901, 0x09c0, 0x0880, 0xc841, 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1,
    0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
    0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1,
    0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, 0x3c00, 0xfcc1, 0xfd81, 0x3d40,
    0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 0x2800, 0xe8c1,
    0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
    0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0,
    0x2080, 0xe041, 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740,
    0xa501, 0x65c0, 0x6480, 0xa441, 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0,
    0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
    0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1,
    0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, 0x5000, 0x90c1, 0x9181, 0x5140,
    0x9301, 0x53c0, 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, 0x9c01, 0x5cc0,
    0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
    0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0,
    0x4c80, 0x8c41, 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341,
    0x4100, 0x81c1, 0x8081, 0x4040,
};
}  // namespace

namespace bluetooth {
namespace l2cap {

void Fcs::Initialize(Fcs& s) {
  s.crc = 0;
}

void Fcs::AddByte(Fcs& s, uint8_t byte) {
  s.crc = ((s.crc >> 8) & 0x00ff) ^ crctab[(s.crc & 0x00ff) ^ byte];
}

uint16_t Fcs::GetChecksum(const Fcs& s) {
  return s.crc;
}

}  // namespace l2cap
}  // namespace bluetooth

system/gd/l2cap/fcs.h

0 → 100644
+38 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <cstdint>

namespace bluetooth {
namespace l2cap {

// Frame Check Sequence from the L2CAP spec.
class Fcs {
 public:
  static void Initialize(Fcs& s);

  static void AddByte(Fcs& s, uint8_t byte);

  static uint16_t GetChecksum(const Fcs& s);

 private:
  uint16_t crc;
};

}  // namespace l2cap
}  // namespace bluetooth
+81 −0
Original line number Diff line number Diff line
@@ -81,5 +81,86 @@ TEST(L2capPacketTest, extendedInformationStartFrameTest) {
  ASSERT_EQ(FrameType::I_FRAME, standard_frame_view.GetFrameType());
}

vector<uint8_t> i_frame_with_fcs = {
    0x0E, 0x00, 0x40, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x38, 0x61,
};
TEST(L2capPacketTest, iFrameWithFcsTest) {
  uint16_t channel_id = 0x0040;
  SegmentationAndReassembly sar = SegmentationAndReassembly::UNSEGMENTED;  // 0
  uint16_t req_seq = 0;
  uint16_t tx_seq = 1;
  RetransmissionDisable r = RetransmissionDisable::NORMAL;  // 0

  std::unique_ptr<RawBuilder> payload = std::make_unique<RawBuilder>();
  vector<uint8_t> payload_bytes = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
  payload->AddOctets(payload_bytes);

  auto packet = StandardInformationFrameWithFcsBuilder::Create(channel_id, tx_seq, r, req_seq, sar, std::move(payload));

  ASSERT_EQ(i_frame_with_fcs.size(), packet->size());
  std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
  BitInserter it(*packet_bytes);
  packet->Serialize(it);
  PacketView<true> packet_bytes_view(packet_bytes);
  ASSERT_EQ(i_frame_with_fcs.size(), packet_bytes_view.size());

  for (size_t i = 0; i < i_frame_with_fcs.size(); i++) {
    ASSERT_EQ(i_frame_with_fcs[i], packet_bytes_view[i]);
  }

  BasicFrameWithFcsView basic_frame_view = BasicFrameWithFcsView::Create(packet_bytes_view);
  ASSERT_TRUE(basic_frame_view.IsValid());
  ASSERT_EQ(channel_id, basic_frame_view.GetChannelId());

  StandardFrameWithFcsView standard_frame_view = StandardFrameWithFcsView::Create(basic_frame_view);
  ASSERT_TRUE(standard_frame_view.IsValid());
  ASSERT_EQ(FrameType::I_FRAME, standard_frame_view.GetFrameType());

  StandardInformationFrameWithFcsView information_frame_view =
      StandardInformationFrameWithFcsView::Create(standard_frame_view);
  ASSERT_TRUE(information_frame_view.IsValid());
  ASSERT_EQ(sar, information_frame_view.GetSar());
  ASSERT_EQ(req_seq, information_frame_view.GetReqSeq());
  ASSERT_EQ(tx_seq, information_frame_view.GetTxSeq());
  ASSERT_EQ(r, information_frame_view.GetR());
}

vector<uint8_t> rr_frame_with_fcs = {
    0x04, 0x00, 0x40, 0x00, 0x01, 0x01, 0xD4, 0x14,
};
TEST(L2capPacketTest, rrFrameWithFcsTest) {
  uint16_t channel_id = 0x0040;
  SupervisoryFunction s = SupervisoryFunction::RECEIVER_READY;  // 0
  RetransmissionDisable r = RetransmissionDisable::NORMAL;      // 0
  uint16_t req_seq = 1;

  auto packet = StandardSupervisoryFrameWithFcsBuilder::Create(channel_id, s, r, req_seq);

  ASSERT_EQ(rr_frame_with_fcs.size(), packet->size());
  std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
  BitInserter it(*packet_bytes);
  packet->Serialize(it);
  PacketView<true> packet_bytes_view(packet_bytes);
  ASSERT_EQ(rr_frame_with_fcs.size(), packet_bytes_view.size());

  for (size_t i = 0; i < rr_frame_with_fcs.size(); i++) {
    ASSERT_EQ(rr_frame_with_fcs[i], packet_bytes_view[i]);
  }

  BasicFrameWithFcsView basic_frame_view = BasicFrameWithFcsView::Create(packet_bytes_view);
  ASSERT_TRUE(basic_frame_view.IsValid());
  ASSERT_EQ(channel_id, basic_frame_view.GetChannelId());

  StandardFrameWithFcsView standard_frame_view = StandardFrameWithFcsView::Create(basic_frame_view);
  ASSERT_TRUE(standard_frame_view.IsValid());
  ASSERT_EQ(FrameType::S_FRAME, standard_frame_view.GetFrameType());

  StandardSupervisoryFrameWithFcsView supervisory_frame_view =
      StandardSupervisoryFrameWithFcsView::Create(standard_frame_view);
  ASSERT_TRUE(supervisory_frame_view.IsValid());
  ASSERT_EQ(s, supervisory_frame_view.GetS());
  ASSERT_EQ(r, supervisory_frame_view.GetR());
  ASSERT_EQ(req_seq, supervisory_frame_view.GetReqSeq());
}
}  // namespace l2cap
}  // namespace bluetooth
+21 −12
Original line number Diff line number Diff line
little_endian_packets

checksum Fcs : 16 "l2cap/"

packet BasicFrame {
  size(payload) : 16,
  ChannelId : 16,
  payload,
}

packet BasicFrameWithFcs {
  checksum_start(Fcs),
  size(payload) : 16,
  ChannelId : 16,
  payload : [+2*8], // Include Fcs in the size
  Fcs : Fcs,
}

// ChannelId 2 is connectionless
packet GroupFrame : BasicFrame (ChannelId = 0x02) {
  Psm : 16,
@@ -41,6 +51,11 @@ packet StandardFrame : BasicFrame {
  body,
}

packet StandardFrameWithFcs : BasicFrameWithFcs {
  FrameType : FrameType,
  body,
}

group StandardSupervisoryControl {
  fixed = 0 : 1,
  S : SupervisoryFunction,
@@ -61,9 +76,8 @@ packet StandardSupervisoryFrame : StandardFrame (FrameType = S_FRAME) {
  StandardSupervisoryControl,
}

packet StandardSupervisoryFrameWithFcs : StandardFrame (FrameType = S_FRAME) {
packet StandardSupervisoryFrameWithFcs : StandardFrameWithFcs (FrameType = S_FRAME) {
  StandardSupervisoryControl,
  Fcs : 16,
}

packet StandardInformationFrame : StandardFrame (FrameType = I_FRAME) {
@@ -71,10 +85,9 @@ packet StandardInformationFrame : StandardFrame (FrameType = I_FRAME) {
  payload,
}

packet StandardInformationFrameWithFcs : StandardFrame (FrameType = I_FRAME) {
packet StandardInformationFrameWithFcs : StandardFrameWithFcs (FrameType = I_FRAME) {
  StandardInformationControl,
  payload,
  Fcs : 16,
}

packet StandardInformationStartFrame : StandardInformationFrame (Sar = START) {
@@ -118,9 +131,8 @@ packet EnhancedSupervisoryFrame : StandardFrame (FrameType = S_FRAME) {
  EnhancedSupervisoryControl,
}

packet EnhancedSupervisoryFrameWithFcs : StandardFrame (FrameType = S_FRAME) {
packet EnhancedSupervisoryFrameWithFcs : StandardFrameWithFcs (FrameType = S_FRAME) {
  EnhancedSupervisoryControl,
  Fcs : 16,
}

packet EnhancedInformationFrame : StandardFrame (FrameType = I_FRAME) {
@@ -128,10 +140,9 @@ packet EnhancedInformationFrame : StandardFrame (FrameType = I_FRAME) {
  payload,
}

packet EnhancedInformationFrameWithFcs : StandardFrame (FrameType = I_FRAME) {
packet EnhancedInformationFrameWithFcs : StandardFrameWithFcs (FrameType = I_FRAME) {
  EnhancedInformationControl,
  payload,
  Fcs : 16,
}

packet EnhancedInformationStartFrame : EnhancedInformationFrame (Sar = START) {
@@ -164,9 +175,8 @@ packet ExtendedSupervisoryFrame : StandardFrame (FrameType = S_FRAME) {
  ExtendedSupervisoryControl,
}

packet ExtendedSupervisoryFrameWithFcs : StandardFrame (FrameType = S_FRAME) {
packet ExtendedSupervisoryFrameWithFcs : StandardFrameWithFcs (FrameType = S_FRAME) {
  ExtendedSupervisoryControl,
  Fcs : 16,
}

packet ExtendedInformationFrame : StandardFrame (FrameType = I_FRAME) {
@@ -174,10 +184,9 @@ packet ExtendedInformationFrame : StandardFrame (FrameType = I_FRAME) {
  payload,
}

packet ExtendedInformationFrameWithFcs : StandardFrame (FrameType = I_FRAME) {
packet ExtendedInformationFrameWithFcs : StandardFrameWithFcs (FrameType = I_FRAME) {
  ExtendedInformationControl,
  payload,
  Fcs : 16,
}

packet ExtendedInformationStartFrame : ExtendedInformationFrame (Sar = START) {
Loading