1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file.
4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/extensions/api/serial/serial_io_handler.h"
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/bind.h"
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/message_loop/message_loop.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace extensions {
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SerialIoHandler::SerialIoHandler()
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : file_(base::kInvalidPlatformFileValue),
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pending_read_buffer_len_(0),
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pending_write_buffer_len_(0) {
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SerialIoHandler::~SerialIoHandler() {
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SerialIoHandler::Initialize(base::PlatformFile file,
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 const ReadCompleteCallback& read_callback,
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 const WriteCompleteCallback& write_callback) {
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(file_, base::kInvalidPlatformFileValue);
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  file_ = file;
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  read_complete_ = read_callback;
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  write_complete_ = write_callback;
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  InitializeImpl();
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SerialIoHandler::Read(int max_bytes) {
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!IsReadPending());
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_read_buffer_ = new net::IOBuffer(max_bytes);
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_read_buffer_len_ = max_bytes;
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  read_canceled_ = false;
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AddRef();
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ReadImpl();
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SerialIoHandler::Write(const std::string& data) {
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!IsWritePending());
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_write_buffer_ = new net::IOBuffer(data.length());
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_write_buffer_len_ = data.length();
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  memcpy(pending_write_buffer_->data(), data.data(), pending_write_buffer_len_);
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  write_canceled_ = false;
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AddRef();
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WriteImpl();
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SerialIoHandler::ReadCompleted(int bytes_read,
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                    api::serial::ReceiveError error) {
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(IsReadPending());
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  read_complete_.Run(std::string(pending_read_buffer_->data(), bytes_read),
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     error);
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_read_buffer_ = NULL;
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_read_buffer_len_ = 0;
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Release();
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SerialIoHandler::WriteCompleted(int bytes_written,
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     api::serial::SendError error) {
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(IsWritePending());
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  write_complete_.Run(bytes_written, error);
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_write_buffer_ = NULL;
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pending_write_buffer_len_ = 0;
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Release();
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool SerialIoHandler::IsReadPending() const {
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return pending_read_buffer_ != NULL;
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool SerialIoHandler::IsWritePending() const {
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return pending_write_buffer_ != NULL;
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SerialIoHandler::CancelRead(api::serial::ReceiveError reason) {
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (IsReadPending()) {
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    read_canceled_ = true;
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    read_cancel_reason_ = reason;
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    CancelReadImpl();
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SerialIoHandler::CancelWrite(api::serial::SendError reason) {
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (IsWritePending()) {
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    write_canceled_ = true;
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    write_cancel_reason_ = reason;
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    CancelWriteImpl();
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SerialIoHandler::QueueReadCompleted(int bytes_read,
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         api::serial::ReceiveError error) {
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FROM_HERE, base::Bind(&SerialIoHandler::ReadCompleted, this,
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            bytes_read, error));
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SerialIoHandler::QueueWriteCompleted(int bytes_written,
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                          api::serial::SendError error) {
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FROM_HERE, base::Bind(&SerialIoHandler::WriteCompleted, this,
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            bytes_written, error));
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace extensions
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
121