[M71 Dev][Tizen] Fix compiler errors
[platform/framework/web/chromium-efl.git] / device / serial / serial_io_handler.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "device/serial/serial_io_handler.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/files/file_path.h"
12 #include "base/location.h"
13 #include "base/strings/string_util.h"
14 #include "base/task/post_task.h"
15 #include "base/task/task_traits.h"
16 #include "build/build_config.h"
17
18 #if defined(OS_CHROMEOS)
19 #include "chromeos/dbus/dbus_thread_manager.h"
20 #include "chromeos/dbus/permission_broker_client.h"
21 #endif  // defined(OS_CHROMEOS)
22
23 namespace device {
24
25 SerialIoHandler::SerialIoHandler(
26     scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner)
27     : ui_thread_task_runner_(ui_thread_task_runner) {
28   options_.bitrate = 9600;
29   options_.data_bits = mojom::SerialDataBits::EIGHT;
30   options_.parity_bit = mojom::SerialParityBit::NO_PARITY;
31   options_.stop_bits = mojom::SerialStopBits::ONE;
32   options_.cts_flow_control = false;
33   options_.has_cts_flow_control = true;
34 }
35
36 SerialIoHandler::~SerialIoHandler() {
37   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
38   Close();
39 }
40
41 void SerialIoHandler::Open(const std::string& port,
42                            const mojom::SerialConnectionOptions& options,
43                            OpenCompleteCallback callback) {
44   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
45   DCHECK(!open_complete_);
46   open_complete_ = std::move(callback);
47   DCHECK(ui_thread_task_runner_.get());
48   MergeConnectionOptions(options);
49   port_ = port;
50
51 #if defined(OS_CHROMEOS)
52   chromeos::PermissionBrokerClient* client =
53       chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient();
54   DCHECK(client) << "Could not get permission_broker client.";
55   // PermissionBrokerClient should be called on the UI thread.
56   scoped_refptr<base::SingleThreadTaskRunner> task_runner =
57       base::ThreadTaskRunnerHandle::Get();
58   ui_thread_task_runner_->PostTask(
59       FROM_HERE,
60       base::BindOnce(
61           &chromeos::PermissionBrokerClient::OpenPath, base::Unretained(client),
62           port, base::Bind(&SerialIoHandler::OnPathOpened, this, task_runner),
63           base::Bind(&SerialIoHandler::OnPathOpenError, this, task_runner)));
64 #else
65   base::PostTaskWithTraits(
66       FROM_HERE,
67       {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
68       base::BindOnce(&SerialIoHandler::StartOpen, this, port,
69                      base::ThreadTaskRunnerHandle::Get()));
70 #endif  // defined(OS_CHROMEOS)
71 }
72
73 #if defined(OS_CHROMEOS)
74
75 void SerialIoHandler::OnPathOpened(
76     scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner,
77     base::ScopedFD fd) {
78   base::File file(fd.release());
79   io_thread_task_runner->PostTask(
80       FROM_HERE,
81       base::BindOnce(&SerialIoHandler::FinishOpen, this, std::move(file)));
82 }
83
84 void SerialIoHandler::OnPathOpenError(
85     scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner,
86     const std::string& error_name,
87     const std::string& error_message) {
88   io_thread_task_runner->PostTask(
89       FROM_HERE, base::BindOnce(&SerialIoHandler::ReportPathOpenError, this,
90                                 error_name, error_message));
91 }
92
93 void SerialIoHandler::ReportPathOpenError(const std::string& error_name,
94                                           const std::string& error_message) {
95   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
96   DCHECK(open_complete_);
97   LOG(ERROR) << "Permission broker failed to open '" << port_
98              << "': " << error_name << ": " << error_message;
99   std::move(open_complete_).Run(false);
100 }
101
102 #endif
103
104 void SerialIoHandler::MergeConnectionOptions(
105     const mojom::SerialConnectionOptions& options) {
106   if (options.bitrate) {
107     options_.bitrate = options.bitrate;
108   }
109   if (options.data_bits != mojom::SerialDataBits::NONE) {
110     options_.data_bits = options.data_bits;
111   }
112   if (options.parity_bit != mojom::SerialParityBit::NONE) {
113     options_.parity_bit = options.parity_bit;
114   }
115   if (options.stop_bits != mojom::SerialStopBits::NONE) {
116     options_.stop_bits = options.stop_bits;
117   }
118   if (options.has_cts_flow_control) {
119     DCHECK(options_.has_cts_flow_control);
120     options_.cts_flow_control = options.cts_flow_control;
121   }
122 }
123
124 void SerialIoHandler::StartOpen(
125     const std::string& port,
126     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
127   DCHECK(open_complete_);
128   DCHECK(!file_.IsValid());
129   // It's the responsibility of the API wrapper around SerialIoHandler to
130   // validate the supplied path against the set of valid port names, and
131   // it is a reasonable assumption that serial port names are ASCII.
132   DCHECK(base::IsStringASCII(port));
133   base::FilePath path(base::FilePath::FromUTF8Unsafe(MaybeFixUpPortName(port)));
134   int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
135               base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_WRITE |
136               base::File::FLAG_EXCLUSIVE_WRITE | base::File::FLAG_ASYNC |
137               base::File::FLAG_TERMINAL_DEVICE;
138   base::File file(path, flags);
139   io_task_runner->PostTask(
140       FROM_HERE,
141       base::BindOnce(&SerialIoHandler::FinishOpen, this, std::move(file)));
142 }
143
144 void SerialIoHandler::FinishOpen(base::File file) {
145   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
146   DCHECK(open_complete_);
147
148   if (!file.IsValid()) {
149     LOG(ERROR) << "Failed to open serial port: "
150                << base::File::ErrorToString(file.error_details());
151     std::move(open_complete_).Run(false);
152     return;
153   }
154
155   file_ = std::move(file);
156
157   bool success = PostOpen() && ConfigurePortImpl();
158   if (!success)
159     Close();
160
161   std::move(open_complete_).Run(success);
162 }
163
164 bool SerialIoHandler::PostOpen() {
165   return true;
166 }
167
168 void SerialIoHandler::Close() {
169   if (file_.IsValid()) {
170     base::PostTaskWithTraits(
171         FROM_HERE,
172         {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
173         base::BindOnce(&SerialIoHandler::DoClose, std::move(file_)));
174   }
175 }
176
177 // static
178 void SerialIoHandler::DoClose(base::File port) {
179   // port closed by destructor.
180 }
181
182 void SerialIoHandler::Read(std::unique_ptr<WritableBuffer> buffer) {
183   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
184   DCHECK(!IsReadPending());
185   pending_read_buffer_ = std::move(buffer);
186   read_canceled_ = false;
187   AddRef();
188   ReadImpl();
189 }
190
191 void SerialIoHandler::Write(std::unique_ptr<ReadOnlyBuffer> buffer) {
192   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
193   DCHECK(!IsWritePending());
194   pending_write_buffer_ = std::move(buffer);
195   write_canceled_ = false;
196   AddRef();
197   WriteImpl();
198 }
199
200 void SerialIoHandler::ReadCompleted(int bytes_read,
201                                     mojom::SerialReceiveError error) {
202   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
203   DCHECK(IsReadPending());
204   std::unique_ptr<WritableBuffer> pending_read_buffer =
205       std::move(pending_read_buffer_);
206   if (error == mojom::SerialReceiveError::NONE) {
207     pending_read_buffer->Done(bytes_read);
208   } else {
209     pending_read_buffer->DoneWithError(bytes_read, static_cast<int32_t>(error));
210   }
211   Release();
212 }
213
214 void SerialIoHandler::WriteCompleted(int bytes_written,
215                                      mojom::SerialSendError error) {
216   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
217   DCHECK(IsWritePending());
218   std::unique_ptr<ReadOnlyBuffer> pending_write_buffer =
219       std::move(pending_write_buffer_);
220   if (error == mojom::SerialSendError::NONE) {
221     pending_write_buffer->Done(bytes_written);
222   } else {
223     pending_write_buffer->DoneWithError(bytes_written,
224                                         static_cast<int32_t>(error));
225   }
226   Release();
227 }
228
229 bool SerialIoHandler::IsReadPending() const {
230   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
231   return pending_read_buffer_ != NULL;
232 }
233
234 bool SerialIoHandler::IsWritePending() const {
235   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
236   return pending_write_buffer_ != NULL;
237 }
238
239 void SerialIoHandler::CancelRead(mojom::SerialReceiveError reason) {
240   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
241   if (IsReadPending() && !read_canceled_) {
242     read_canceled_ = true;
243     read_cancel_reason_ = reason;
244     CancelReadImpl();
245   }
246 }
247
248 void SerialIoHandler::CancelWrite(mojom::SerialSendError reason) {
249   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
250   if (IsWritePending() && !write_canceled_) {
251     write_canceled_ = true;
252     write_cancel_reason_ = reason;
253     CancelWriteImpl();
254   }
255 }
256
257 bool SerialIoHandler::ConfigurePort(
258     const mojom::SerialConnectionOptions& options) {
259   MergeConnectionOptions(options);
260   return ConfigurePortImpl();
261 }
262
263 void SerialIoHandler::QueueReadCompleted(int bytes_read,
264                                          mojom::SerialReceiveError error) {
265   base::ThreadTaskRunnerHandle::Get()->PostTask(
266       FROM_HERE,
267       base::BindOnce(&SerialIoHandler::ReadCompleted, this, bytes_read, error));
268 }
269
270 void SerialIoHandler::QueueWriteCompleted(int bytes_written,
271                                           mojom::SerialSendError error) {
272   base::ThreadTaskRunnerHandle::Get()->PostTask(
273       FROM_HERE, base::BindOnce(&SerialIoHandler::WriteCompleted, this,
274                                 bytes_written, error));
275 }
276
277 }  // namespace device