blob: ee2cc39c325080bc6c6e318a455cfe5055a8699d [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TOOLS_BATTOR_AGENT_BATTOR_CONNECTION_IMPL_H_
#define TOOLS_BATTOR_AGENT_BATTOR_CONNECTION_IMPL_H_
#include <fstream>
#include <memory>
#include <vector>
#include "base/callback_forward.h"
#include "base/cancelable_callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/time/tick_clock.h"
#include "services/device/public/mojom/serial.mojom.h"
#include "tools/battor_agent/battor_connection.h"
#include "tools/battor_agent/battor_error.h"
#include "tools/battor_agent/battor_protocol_types.h"
namespace device {
class SerialIoHandler;
}
namespace net {
class IOBuffer;
}
namespace battor {
// A BattOrConnectionImpl is a concrete implementation of a BattOrConnection.
class BattOrConnectionImpl
: public BattOrConnection,
public base::SupportsWeakPtr<BattOrConnectionImpl> {
public:
BattOrConnectionImpl(
const std::string& path,
BattOrConnection::Listener* listener,
scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner);
~BattOrConnectionImpl() override;
void Open() override;
void Close() override;
bool IsOpen() override;
void SendBytes(BattOrMessageType type,
const void* buffer,
size_t bytes_to_send) override;
void ReadMessage(BattOrMessageType type) override;
void CancelReadMessage() override;
void LogSerial(const std::string& str) override;
// Flushes the serial connection to the BattOr, reading and throwing away
// bytes from the serial connection until the connection is quiet for a
// sufficiently long time. This also discards any trailing bytes from past
// successful reads.
void Flush() override;
protected:
// Overridden by the test to use a fake serial connection.
virtual scoped_refptr<device::SerialIoHandler> CreateIoHandler();
// IO handler capable of reading and writing from the serial connection.
scoped_refptr<device::SerialIoHandler> io_handler_;
const base::TickClock* tick_clock_;
private:
void OnOpened(bool success);
// Reads the specified number of additional bytes and adds them to the pending
// read buffer.
void BeginReadBytesForMessage(size_t bytes_to_read);
// Internal callback for when bytes are read. This method may trigger
// additional reads if any newly read bytes are escape bytes.
void OnBytesReadForMessage(int bytes_read,
device::mojom::SerialReceiveError error);
void EndReadBytesForMessage(bool success,
BattOrMessageType type,
std::unique_ptr<std::vector<char>> data);
void BeginReadBytesForFlush();
void OnBytesReadForFlush(int bytes_read,
device::mojom::SerialReceiveError error);
void SetTimeout(base::TimeDelta timeout);
// Pulls off the next complete message from already_read_buffer_, returning
// its type and contents through out parameters and any error that occurred
// through the return value.
enum ParseMessageError {
NONE = 0,
NOT_ENOUGH_BYTES = 1,
MISSING_START_BYTE = 2,
INVALID_MESSAGE_TYPE = 3,
TOO_MANY_START_BYTES = 4
};
ParseMessageError ParseMessage(BattOrMessageType* type,
std::vector<char>* data);
// Internal callback for when bytes are sent.
void OnBytesSent(int bytes_sent, device::mojom::SerialSendError error);
// The path of the BattOr.
std::string path_;
// Indicates whether the connection is currently open.
bool is_open_;
// All bytes that have already been read from the serial stream, but have not
// yet been given to the listener as a complete message.
std::vector<char> already_read_buffer_;
// The bytes that were read in the pending read.
scoped_refptr<net::IOBuffer> pending_read_buffer_;
// The type of message we're looking for in the pending read.
BattOrMessageType pending_read_message_type_;
// The total number of bytes that we're expecting to send.
size_t pending_write_length_;
// The start of the period over which no bytes must be read from the serial
// connection in order for Flush() to be considered complete.
base::TimeTicks flush_quiet_period_start_;
// The timeout for the current action.
base::CancelableClosure timeout_callback_;
// Threads needed for serial communication.
scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_;
std::fstream serial_log_;
DISALLOW_COPY_AND_ASSIGN(BattOrConnectionImpl);
};
} // namespace battor
#endif // TOOLS_BATTOR_AGENT_BATTOR_CONNECTION_IMPL_H_