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

Commit 0fecf8d3 authored by Dennis Cheng's avatar Dennis Cheng
Browse files

test_vendor_lib: Use EPOLLOUT

HciTransport checks for write-readiness before sending any packets
back to the HCI. Packets are maintained on a queue and only written
when the EPOLLOUT flag is set in the epoll_event.

Bug: 21586676
Change-Id: Iebd9599286b62746e2be7e424c522058ae978bb1
parent 15f566c4
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
#
#
#  Copyright (C) 2015 Google, Inc.
#
#  Licensed under the Apache License, Version 2.0 (the "License");
+6 −6
Original line number Diff line number Diff line
@@ -34,6 +34,12 @@ namespace test_vendor_lib {
// controller object) instead of registering its methods as callbacks?
class BREDRController {
 public:
  // Registers command callbacks with the HciHandler instance so that they are
  // fired when the corresponding opcode is received from the HCI. For now, each
  // command must be individually registered. This allows for some flexibility
  // in which commands are made available by which controller.
  void RegisterHandlerCallbacks();

  // Functions that operate on the global controller instance. Initialize()
  // is called by the vendor library's Init() function to create the global
  // controller and must be called before Get() and CleanUp().
@@ -66,12 +72,6 @@ class BREDRController {
  // CleanUp() method that destructs the global controller.
  ~BREDRController() = default;

  // Registers command callbacks with the HciHandler instance so that they are
  // fired when the corresponding opcode is received from the HCI. For now, each
  // command must be individually registered. This allows for some flexibility
  // in which commands are made available by which controller.
  void RegisterHandlerCallbacks();

  // Maintains the commands to be registered and used in the HciHandler object.
  // Keys are command opcodes and values are the callbacks to handle each
  // command.
+4 −4
Original line number Diff line number Diff line
@@ -35,6 +35,10 @@ namespace test_vendor_lib {
// object and called when commands and data are sent by the host.
class HciHandler {
 public:
  // Sets the command and data callbacks for when packets are received from the
  // HCI.
  void RegisterTransportCallbacks();

  // Functions that operate on the global handler instance. Initialize()
  // is called by the vendor library's Init() function to create the global
  // handler and must be called before Get() and CleanUp().
@@ -69,10 +73,6 @@ class HciHandler {
  // CleanUp() method that destructs the global handler.
  ~HciHandler() = default;

  // Sets the command and data callbacks for when packets are received from the
  // HCI.
  void RegisterTransportCallbacks();

  // Disallow any copies of the singleton to be made.
  DISALLOW_COPY_AND_ASSIGN(HciHandler);

+20 −10
Original line number Diff line number Diff line
@@ -7,8 +7,7 @@
//
// 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,
// 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.
@@ -23,6 +22,7 @@

#include <functional>
#include <memory>
#include <queue>

#include <base/macros.h>

@@ -69,19 +69,25 @@ class HciTransport {
  void RegisterCommandCallback(
      std::function<void(std::unique_ptr<CommandPacket>)> callback);

  // TODO(dennischeng): Determine correct management of event object, what if
  // write doesn't finish before destruction?
  void SendEvent(const EventPacket& event);
  // Posts the event onto |outgoing_events_| to be written whenever the HCI file
  // descriptor is ready for writing.
  void SendEvent(std::unique_ptr<EventPacket> event);

 private:
  // Loops through the epoll event buffer and receives packets if they are
  // ready. Fires the corresponding handler callback for each received packet.
  bool ReceiveReadyPackets(const epoll_event& event_buffer,
                          int num_ready);
  bool CheckReadyEpollEvents(const epoll_event& event_buffer, int num_ready);

  // Receives a packet from the HCI whenever the event loop signals that there
  // is data to be received.
  bool ReceiveReadyPacket() const;

  // Reads in a command packet and calls the handler's command ready callback,
  // passing owernship of the command packet to the handler.
  void ReceiveReadyCommand();
  void ReceiveReadyCommand() const;

  // Sends the event at the front of |outgoing_events_| to the HCI.
  bool SendReadyEvent();

  // There will only be one global instance of the HCI transport used by
  // bt_vendor.cc and accessed via the static GetInstance() function.
@@ -96,8 +102,9 @@ class HciTransport {
  // TODO(dennischeng): import base/ and use a MessageLoopForIO for event loop.
  bool ConfigEpoll();

  // Disallow any copies of the singleton to be made.
  DISALLOW_COPY_AND_ASSIGN(HciTransport);
  // Write queue for sending events to the HCI. Event packets are removed from
  // the queue and written when write-readiness is signalled.
  std::queue<std::unique_ptr<EventPacket>> outgoing_events_;

  // Callback executed in Listen() for command packets.
  std::function<void(std::unique_ptr<CommandPacket>)> command_callback_;
@@ -115,6 +122,9 @@ class HciTransport {
  // |socketpair_fds_[0]| is the listener end and is closed in the PacketStream
  // object. |socketpair_fds_[1]| is the HCI end and is closed in bt_vendor.cc.
  int socketpair_fds_[2];

  // Disallow any copies of the singleton to be made.
  DISALLOW_COPY_AND_ASSIGN(HciTransport);
};

}  // namespace test_vendor_lib
+8 −8
Original line number Diff line number Diff line
@@ -41,15 +41,15 @@ class PacketStream {

  // Reads a command packet and returns the packet back to the caller, along
  // with the responsibility of managing the packet's memory.
  std::unique_ptr<CommandPacket> ReceiveCommand();
  std::unique_ptr<CommandPacket> ReceiveCommand() const;

  // Reads and interprets a single octet as a packet type octet. Validates the
  // type octet for correctness.
  serial_data_type_t ReceivePacketType();
  serial_data_type_t ReceivePacketType() const;

  // Sends an event to the HCI. The memory management and ownership of the event
  // is left with the caller.
  void SendEvent(const EventPacket& event);
  bool SendEvent(const EventPacket& event) const;

  // Sets the file descriptor used in reading and writing. The PacketStream
  // takes ownership of the descriptor at |fd| and closes it during destruction.
@@ -62,15 +62,15 @@ class PacketStream {
  // DATA_TYPE_SCO.
  bool ValidateTypeOctet(serial_data_type_t type) const;

  // Attempts to receive |num_octets_to_receive| into |buffer|, returning
  // Attempts to receive |num_octets_to_receive| into |destination|, returning
  // false if an error occurs.
  bool ReceiveData(std::vector<std::uint8_t>& buffer,
                  size_t num_octets_to_receive);
  bool ReceiveAll(std::vector<std::uint8_t>& destination,
                  size_t num_octets_to_receive) const;

  // Attempts to send |num_octets_to_send| from |source|, returning false if an
  // error occurs.
  bool SendData(const std::vector<std::uint8_t>& source,
               size_t num_octets_to_send);
  bool SendAll(const std::vector<std::uint8_t>& source,
               size_t num_octets_to_send) const;

  // File descriptor to read from and write to. This is the descriptor given to
  // the HCI from the HciTransport.
Loading