15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file.
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "device/serial/serial_connection_factory.h"
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/bind.h"
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/location.h"
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "device/serial/serial_connection.h"
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "device/serial/serial_io_handler.h"
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace device {
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace {
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void FillDefaultConnectionOptions(serial::ConnectionOptions* options) {
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!options->bitrate)
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    options->bitrate = 9600;
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (options->data_bits == serial::DATA_BITS_NONE)
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    options->data_bits = serial::DATA_BITS_EIGHT;
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (options->stop_bits == serial::STOP_BITS_NONE)
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    options->stop_bits = serial::STOP_BITS_ONE;
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (options->parity_bit == serial::PARITY_BIT_NONE)
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    options->parity_bit = serial::PARITY_BIT_NO;
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!options->has_cts_flow_control) {
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    options->has_cts_flow_control = true;
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    options->cts_flow_control = false;
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class SerialConnectionFactory::ConnectTask
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : public base::RefCountedThreadSafe<SerialConnectionFactory::ConnectTask> {
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public:
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ConnectTask(scoped_refptr<SerialConnectionFactory> factory,
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              const std::string& path,
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              serial::ConnectionOptionsPtr options,
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              mojo::InterfaceRequest<serial::Connection> connection_request,
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              mojo::InterfaceRequest<serial::DataSink> sink,
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              mojo::InterfaceRequest<serial::DataSource> source);
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void Run();
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private:
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  friend class base::RefCountedThreadSafe<SerialConnectionFactory::ConnectTask>;
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual ~ConnectTask();
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void Connect();
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void OnConnected(bool success);
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<SerialConnectionFactory> factory_;
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const std::string path_;
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  serial::ConnectionOptionsPtr options_;
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  mojo::InterfaceRequest<serial::Connection> connection_request_;
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojo::InterfaceRequest<serial::DataSink> sink_;
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojo::InterfaceRequest<serial::DataSource> source_;
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<SerialIoHandler> io_handler_;
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ConnectTask);
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SerialConnectionFactory::SerialConnectionFactory(
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const IoHandlerFactory& io_handler_factory,
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_refptr<base::MessageLoopProxy> connect_message_loop)
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : io_handler_factory_(io_handler_factory),
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      connect_message_loop_(connect_message_loop) {
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SerialConnectionFactory::CreateConnection(
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& path,
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    serial::ConnectionOptionsPtr options,
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    mojo::InterfaceRequest<serial::Connection> connection_request,
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    mojo::InterfaceRequest<serial::DataSink> sink,
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    mojo::InterfaceRequest<serial::DataSource> source) {
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<ConnectTask> task(new ConnectTask(this,
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                  path,
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                  options.Pass(),
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                  connection_request.Pass(),
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                  sink.Pass(),
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                  source.Pass()));
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  task->Run();
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SerialConnectionFactory::~SerialConnectionFactory() {
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SerialConnectionFactory::ConnectTask::ConnectTask(
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_refptr<SerialConnectionFactory> factory,
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& path,
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    serial::ConnectionOptionsPtr options,
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    mojo::InterfaceRequest<serial::Connection> connection_request,
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    mojo::InterfaceRequest<serial::DataSink> sink,
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    mojo::InterfaceRequest<serial::DataSource> source)
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : factory_(factory),
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      path_(path),
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      options_(options.Pass()),
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      connection_request_(connection_request.Pass()),
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      sink_(sink.Pass()),
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      source_(source.Pass()) {
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SerialConnectionFactory::ConnectTask::Run() {
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  factory_->connect_message_loop_->PostTask(
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      FROM_HERE,
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&SerialConnectionFactory::ConnectTask::Connect, this));
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SerialConnectionFactory::ConnectTask::~ConnectTask() {
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SerialConnectionFactory::ConnectTask::Connect() {
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  io_handler_ = factory_->io_handler_factory_.Run();
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  io_handler_->Open(
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      path_,
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&SerialConnectionFactory::ConnectTask::OnConnected, this));
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SerialConnectionFactory::ConnectTask::OnConnected(bool success) {
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(io_handler_.get());
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!success)
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!options_)
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    options_ = serial::ConnectionOptions::New();
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  FillDefaultConnectionOptions(options_.get());
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!io_handler_->ConfigurePort(*options_))
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojo::BindToRequest(
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new SerialConnection(io_handler_, sink_.Pass(), source_.Pass()),
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      &connection_request_);
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace device
131