root/chrome/browser/extensions/api/serial/serial_api.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. SetDefaultScopedPtrValue
  2. PrePrepare
  3. Respond
  4. GetSerialConnection
  5. RemoveSerialConnection
  6. Prepare
  7. Work
  8. Prepare
  9. AsyncWorkStart
  10. OnConnected
  11. FinishConnect
  12. CreateSerialConnection
  13. Prepare
  14. Work
  15. Prepare
  16. Work
  17. Prepare
  18. AsyncWorkStart
  19. OnSendComplete
  20. Prepare
  21. Work
  22. Prepare
  23. Work
  24. Prepare
  25. Work
  26. Prepare
  27. Work
  28. Prepare
  29. Work
  30. Prepare
  31. Work

// Copyright 2012 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.

#include "chrome/browser/extensions/api/serial/serial_api.h"

#include <algorithm>

#include "base/values.h"
#include "chrome/browser/extensions/api/serial/serial_connection.h"
#include "chrome/browser/extensions/api/serial/serial_event_dispatcher.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/serial.h"
#include "content/public/browser/browser_thread.h"
#include "device/serial/serial_device_enumerator.h"
#include "extensions/browser/extension_system.h"

using content::BrowserThread;

namespace extensions {

namespace api {

namespace {

// It's a fool's errand to come up with a default bitrate, because we don't get
// to control both sides of the communication. Unless the other side has
// implemented auto-bitrate detection (rare), if we pick the wrong rate, then
// you're gonna have a bad time. Close doesn't count.
//
// But we'd like to pick something that has a chance of working, and 9600 is a
// good balance between popularity and speed. So 9600 it is.
const int kDefaultBufferSize = 4096;
const int kDefaultBitrate = 9600;
const serial::DataBits kDefaultDataBits = serial::DATA_BITS_EIGHT;
const serial::ParityBit kDefaultParityBit = serial::PARITY_BIT_NO;
const serial::StopBits kDefaultStopBits = serial::STOP_BITS_ONE;
const int kDefaultReceiveTimeout = 0;
const int kDefaultSendTimeout = 0;

const char kErrorConnectFailed[] = "Failed to connect to the port.";
const char kErrorSerialConnectionNotFound[] = "Serial connection not found.";
const char kErrorGetControlSignalsFailed[] = "Failed to get control signals.";

template <class T>
void SetDefaultScopedPtrValue(scoped_ptr<T>& ptr, const T& value) {
  if (!ptr.get())
    ptr.reset(new T(value));
}

}  // namespace

SerialAsyncApiFunction::SerialAsyncApiFunction()
    : manager_(NULL) {
}

SerialAsyncApiFunction::~SerialAsyncApiFunction() {}

bool SerialAsyncApiFunction::PrePrepare() {
  manager_ = ApiResourceManager<SerialConnection>::Get(browser_context());
  DCHECK(manager_);
  return true;
}

bool SerialAsyncApiFunction::Respond() {
  return error_.empty();
}

SerialConnection* SerialAsyncApiFunction::GetSerialConnection(
    int api_resource_id) {
  return manager_->Get(extension_->id(), api_resource_id);
}

void SerialAsyncApiFunction::RemoveSerialConnection(int api_resource_id) {
  manager_->Remove(extension_->id(), api_resource_id);
}

SerialGetDevicesFunction::SerialGetDevicesFunction() {}

bool SerialGetDevicesFunction::Prepare() {
  set_work_thread_id(BrowserThread::FILE);
  return true;
}

void SerialGetDevicesFunction::Work() {
  DCHECK_CURRENTLY_ON(BrowserThread::FILE);

  device::SerialDeviceInfoList devices;
  scoped_ptr<device::SerialDeviceEnumerator> enumerator =
      device::SerialDeviceEnumerator::Create();
  enumerator->GetDevices(&devices);

  std::vector<linked_ptr<serial::DeviceInfo> > out_devices;
  for (device::SerialDeviceInfoList::const_iterator iter = devices.begin();
       iter != devices.end();
       ++iter) {
    linked_ptr<device::SerialDeviceInfo> device = *iter;
    linked_ptr<serial::DeviceInfo> info(new serial::DeviceInfo);
    info->path = device->path;
    if (device->vendor_id)
      info->vendor_id.reset(new int(static_cast<int>(*device->vendor_id)));
    if (device->product_id)
      info->product_id.reset(new int(static_cast<int>(*device->product_id)));
    info->display_name.reset(device->display_name.release());
    out_devices.push_back(info);
  }

  results_ = serial::GetDevices::Results::Create(out_devices);
}

SerialConnectFunction::SerialConnectFunction() {}

SerialConnectFunction::~SerialConnectFunction() {}

bool SerialConnectFunction::Prepare() {
  params_ = serial::Connect::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());

  // Fill in any omitted options to ensure a known initial configuration.
  if (!params_->options.get())
    params_->options.reset(new serial::ConnectionOptions());
  serial::ConnectionOptions* options = params_->options.get();

  SetDefaultScopedPtrValue(options->persistent, false);
  SetDefaultScopedPtrValue(options->buffer_size, kDefaultBufferSize);
  SetDefaultScopedPtrValue(options->bitrate, kDefaultBitrate);
  SetDefaultScopedPtrValue(options->cts_flow_control, false);
  SetDefaultScopedPtrValue(options->receive_timeout, kDefaultReceiveTimeout);
  SetDefaultScopedPtrValue(options->send_timeout, kDefaultSendTimeout);

  if (options->data_bits == serial::DATA_BITS_NONE)
    options->data_bits = kDefaultDataBits;
  if (options->parity_bit == serial::PARITY_BIT_NONE)
    options->parity_bit = kDefaultParityBit;
  if (options->stop_bits == serial::STOP_BITS_NONE)
    options->stop_bits = kDefaultStopBits;

  serial_event_dispatcher_ = SerialEventDispatcher::Get(browser_context());
  DCHECK(serial_event_dispatcher_);

  return true;
}

void SerialConnectFunction::AsyncWorkStart() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  connection_ = CreateSerialConnection(params_->path, extension_->id());
  connection_->Open(base::Bind(&SerialConnectFunction::OnConnected, this));
}

void SerialConnectFunction::OnConnected(bool success) {
  DCHECK(connection_);

  if (success) {
    if (!connection_->Configure(*params_->options.get())) {
      connection_->Close();
      delete connection_;
      connection_ = NULL;
    }
  } else {
    delete connection_;
    connection_ = NULL;
  }

  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
                          base::Bind(&SerialConnectFunction::FinishConnect,
                                     this));
}

void SerialConnectFunction::FinishConnect() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (!connection_) {
    error_ = kErrorConnectFailed;
  } else {
    int id = manager_->Add(connection_);
    serial::ConnectionInfo info;
    info.connection_id = id;
    if (connection_->GetInfo(&info)) {
      serial_event_dispatcher_->PollConnection(extension_->id(), id);
      results_ = serial::Connect::Results::Create(info);
    } else {
      connection_->Close();
      RemoveSerialConnection(id);
      error_ = kErrorConnectFailed;
    }
  }
  AsyncWorkCompleted();
}

SerialConnection* SerialConnectFunction::CreateSerialConnection(
    const std::string& port, const std::string& extension_id) const {
  return new SerialConnection(port, extension_id);
}

SerialUpdateFunction::SerialUpdateFunction() {}

SerialUpdateFunction::~SerialUpdateFunction() {}

bool SerialUpdateFunction::Prepare() {
  params_ = serial::Update::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());

  return true;
}

void SerialUpdateFunction::Work() {
  SerialConnection* connection = GetSerialConnection(params_->connection_id);
  if (!connection) {
    error_ = kErrorSerialConnectionNotFound;
    return;
  }
  bool success = connection->Configure(params_->options);
  results_ = serial::Update::Results::Create(success);
}

SerialDisconnectFunction::SerialDisconnectFunction() {}

SerialDisconnectFunction::~SerialDisconnectFunction() {}

bool SerialDisconnectFunction::Prepare() {
  params_ = serial::Disconnect::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());

  return true;
}

void SerialDisconnectFunction::Work() {
  SerialConnection* connection = GetSerialConnection(params_->connection_id);
  if (!connection) {
    error_ = kErrorSerialConnectionNotFound;
    return;
  }
  connection->Close();
  RemoveSerialConnection(params_->connection_id);
  results_ = serial::Disconnect::Results::Create(true);
}

SerialSendFunction::SerialSendFunction() {}

SerialSendFunction::~SerialSendFunction() {}

bool SerialSendFunction::Prepare() {
  params_ = serial::Send::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());

  return true;
}

void SerialSendFunction::AsyncWorkStart() {
  SerialConnection* connection = GetSerialConnection(params_->connection_id);
  if (!connection) {
    error_ = kErrorSerialConnectionNotFound;
    AsyncWorkCompleted();
    return;
  }

  if (!connection->Send(params_->data,
                        base::Bind(&SerialSendFunction::OnSendComplete,
                                   this))) {
    OnSendComplete(0, serial::SEND_ERROR_PENDING);
  }
}

void SerialSendFunction::OnSendComplete(int bytes_sent,
                                        serial::SendError error) {
  serial::SendInfo send_info;
  send_info.bytes_sent = bytes_sent;
  send_info.error = error;
  results_ = serial::Send::Results::Create(send_info);
  AsyncWorkCompleted();
}

SerialFlushFunction::SerialFlushFunction() {}

SerialFlushFunction::~SerialFlushFunction() {}

bool SerialFlushFunction::Prepare() {
  params_ = serial::Flush::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());
  return true;
}

void SerialFlushFunction::Work() {
  SerialConnection* connection = GetSerialConnection(params_->connection_id);
  if (!connection) {
    error_ = kErrorSerialConnectionNotFound;
    return;
  }

  bool success = connection->Flush();
  results_ = serial::Flush::Results::Create(success);
}

SerialSetPausedFunction::SerialSetPausedFunction() {}

SerialSetPausedFunction::~SerialSetPausedFunction() {}

bool SerialSetPausedFunction::Prepare() {
  params_ = serial::SetPaused::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());

  serial_event_dispatcher_ = SerialEventDispatcher::Get(browser_context());
  DCHECK(serial_event_dispatcher_);
  return true;
}

void SerialSetPausedFunction::Work() {
  SerialConnection* connection = GetSerialConnection(params_->connection_id);
  if (!connection) {
    error_ = kErrorSerialConnectionNotFound;
    return;
  }

  if (params_->paused != connection->paused()) {
    connection->set_paused(params_->paused);
    if (!params_->paused) {
      serial_event_dispatcher_->PollConnection(extension_->id(),
                                               params_->connection_id);
    }
  }

  results_ = serial::SetPaused::Results::Create();
}

SerialGetInfoFunction::SerialGetInfoFunction() {}

SerialGetInfoFunction::~SerialGetInfoFunction() {}

bool SerialGetInfoFunction::Prepare() {
  params_ = serial::GetInfo::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());

  return true;
}

void SerialGetInfoFunction::Work() {
  SerialConnection* connection = GetSerialConnection(params_->connection_id);
  if (!connection) {
    error_ = kErrorSerialConnectionNotFound;
    return;
  }

  serial::ConnectionInfo info;
  info.connection_id = params_->connection_id;
  connection->GetInfo(&info);
  results_ = serial::GetInfo::Results::Create(info);
}

SerialGetConnectionsFunction::SerialGetConnectionsFunction() {}

SerialGetConnectionsFunction::~SerialGetConnectionsFunction() {}

bool SerialGetConnectionsFunction::Prepare() {
  return true;
}

void SerialGetConnectionsFunction::Work() {
  std::vector<linked_ptr<serial::ConnectionInfo> > infos;
  const base::hash_set<int>* connection_ids = manager_->GetResourceIds(
      extension_->id());
  if (connection_ids) {
    for (base::hash_set<int>::const_iterator it = connection_ids->begin();
         it != connection_ids->end(); ++it) {
      int connection_id = *it;
      SerialConnection *connection = GetSerialConnection(connection_id);
      if (connection) {
        linked_ptr<serial::ConnectionInfo> info(new serial::ConnectionInfo());
        info->connection_id = connection_id;
        connection->GetInfo(info.get());
        infos.push_back(info);
      }
    }
  }
  results_ = serial::GetConnections::Results::Create(infos);
}

SerialGetControlSignalsFunction::SerialGetControlSignalsFunction() {}

SerialGetControlSignalsFunction::~SerialGetControlSignalsFunction() {}

bool SerialGetControlSignalsFunction::Prepare() {
  params_ = serial::GetControlSignals::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());

  return true;
}

void SerialGetControlSignalsFunction::Work() {
  SerialConnection* connection = GetSerialConnection(params_->connection_id);
  if (!connection) {
    error_ = kErrorSerialConnectionNotFound;
    return;
  }

  serial::DeviceControlSignals signals;
  if (!connection->GetControlSignals(&signals)) {
    error_ = kErrorGetControlSignalsFailed;
    return;
  }

  results_ = serial::GetControlSignals::Results::Create(signals);
}

SerialSetControlSignalsFunction::SerialSetControlSignalsFunction() {}

SerialSetControlSignalsFunction::~SerialSetControlSignalsFunction() {}

bool SerialSetControlSignalsFunction::Prepare() {
  params_ = serial::SetControlSignals::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());

  return true;
}

void SerialSetControlSignalsFunction::Work() {
  SerialConnection* connection = GetSerialConnection(params_->connection_id);
  if (!connection) {
    error_ = kErrorSerialConnectionNotFound;
    return;
  }

  bool success = connection->SetControlSignals(params_->signals);
  results_ = serial::SetControlSignals::Results::Create(success);
}

}  // namespace api

}  // namespace extensions

/* [<][>][^][v][top][bottom][index][help] */