[M73 Dev][Tizen] Fix linker errors
[platform/framework/web/chromium-efl.git] / services / 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 "services/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     const base::FilePath& port,
27     scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner)
28     : port_(port), ui_thread_task_runner_(ui_thread_task_runner) {
29   options_.bitrate = 9600;
30   options_.data_bits = mojom::SerialDataBits::EIGHT;
31   options_.parity_bit = mojom::SerialParityBit::NO_PARITY;
32   options_.stop_bits = mojom::SerialStopBits::ONE;
33   options_.cts_flow_control = false;
34   options_.has_cts_flow_control = true;
35 }
36
37 SerialIoHandler::~SerialIoHandler() {
38   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
39   Close();
40 }
41
42 void SerialIoHandler::Open(const mojom::SerialConnectionOptions& options,
43                            OpenCompleteCallback callback) {
44   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
45   DCHECK(!open_complete_);
46   DCHECK(!port_.empty());
47   open_complete_ = std::move(callback);
48   DCHECK(ui_thread_task_runner_.get());
49   MergeConnectionOptions(options);
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(&chromeos::PermissionBrokerClient::OpenPath,
61                      base::Unretained(client), port_.value(),
62                      base::BindRepeating(&SerialIoHandler::OnPathOpened, this,
63                                          task_runner),
64                      base::BindRepeating(&SerialIoHandler::OnPathOpenError,
65                                          this, task_runner)));
66 #else
67   base::PostTaskWithTraits(
68       FROM_HERE,
69       {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
70       base::BindOnce(&SerialIoHandler::StartOpen, this,
71                      base::ThreadTaskRunnerHandle::Get()));
72 #endif  // defined(OS_CHROMEOS)
73 }
74
75 #if defined(OS_CHROMEOS)
76
77 void SerialIoHandler::OnPathOpened(
78     scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner,
79     base::ScopedFD fd) {
80   base::File file(fd.release());
81   io_thread_task_runner->PostTask(
82       FROM_HERE,
83       base::BindOnce(&SerialIoHandler::FinishOpen, this, std::move(file)));
84 }
85
86 void SerialIoHandler::OnPathOpenError(
87     scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner,
88     const std::string& error_name,
89     const std::string& error_message) {
90   io_thread_task_runner->PostTask(
91       FROM_HERE, base::BindOnce(&SerialIoHandler::ReportPathOpenError, this,
92                                 error_name, error_message));
93 }
94
95 void SerialIoHandler::ReportPathOpenError(const std::string& error_name,
96                                           const std::string& error_message) {
97   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
98   DCHECK(open_complete_);
99   LOG(ERROR) << "Permission broker failed to open '" << port_
100              << "': " << error_name << ": " << error_message;
101   std::move(open_complete_).Run(false);
102 }
103
104 #endif
105
106 void SerialIoHandler::MergeConnectionOptions(
107     const mojom::SerialConnectionOptions& options) {
108   if (options.bitrate) {
109     options_.bitrate = options.bitrate;
110   }
111   if (options.data_bits != mojom::SerialDataBits::NONE) {
112     options_.data_bits = options.data_bits;
113   }
114   if (options.parity_bit != mojom::SerialParityBit::NONE) {
115     options_.parity_bit = options.parity_bit;
116   }
117   if (options.stop_bits != mojom::SerialStopBits::NONE) {
118     options_.stop_bits = options.stop_bits;
119   }
120   if (options.has_cts_flow_control) {
121     DCHECK(options_.has_cts_flow_control);
122     options_.cts_flow_control = options.cts_flow_control;
123   }
124 }
125
126 void SerialIoHandler::StartOpen(
127     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
128   DCHECK(open_complete_);
129   DCHECK(!file_.IsValid());
130   int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
131               base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_WRITE |
132               base::File::FLAG_EXCLUSIVE_WRITE | base::File::FLAG_ASYNC |
133               base::File::FLAG_TERMINAL_DEVICE;
134   base::File file(port_, flags);
135   io_task_runner->PostTask(
136       FROM_HERE,
137       base::BindOnce(&SerialIoHandler::FinishOpen, this, std::move(file)));
138 }
139
140 void SerialIoHandler::FinishOpen(base::File file) {
141   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
142   DCHECK(open_complete_);
143
144   if (!file.IsValid()) {
145     LOG(ERROR) << "Failed to open serial port: "
146                << base::File::ErrorToString(file.error_details());
147     std::move(open_complete_).Run(false);
148     return;
149   }
150
151   file_ = std::move(file);
152
153   bool success = PostOpen() && ConfigurePortImpl();
154   if (!success)
155     Close();
156
157   std::move(open_complete_).Run(success);
158 }
159
160 bool SerialIoHandler::PostOpen() {
161   return true;
162 }
163
164 void SerialIoHandler::Close() {
165   if (file_.IsValid()) {
166     base::PostTaskWithTraits(
167         FROM_HERE,
168         {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
169         base::BindOnce(&SerialIoHandler::DoClose, std::move(file_)));
170   }
171 }
172
173 // static
174 void SerialIoHandler::DoClose(base::File port) {
175   // port closed by destructor.
176 }
177
178 void SerialIoHandler::Read(std::unique_ptr<WritableBuffer> buffer) {
179   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
180   DCHECK(!IsReadPending());
181   pending_read_buffer_ = std::move(buffer);
182   read_canceled_ = false;
183   AddRef();
184   ReadImpl();
185 }
186
187 void SerialIoHandler::Write(std::unique_ptr<ReadOnlyBuffer> buffer) {
188   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
189   DCHECK(!IsWritePending());
190   pending_write_buffer_ = std::move(buffer);
191   write_canceled_ = false;
192   AddRef();
193   WriteImpl();
194 }
195
196 void SerialIoHandler::ReadCompleted(int bytes_read,
197                                     mojom::SerialReceiveError error) {
198   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
199   DCHECK(IsReadPending());
200   std::unique_ptr<WritableBuffer> pending_read_buffer =
201       std::move(pending_read_buffer_);
202   if (error == mojom::SerialReceiveError::NONE) {
203     pending_read_buffer->Done(bytes_read);
204   } else {
205     pending_read_buffer->DoneWithError(bytes_read, static_cast<int32_t>(error));
206   }
207   Release();
208 }
209
210 void SerialIoHandler::WriteCompleted(int bytes_written,
211                                      mojom::SerialSendError error) {
212   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
213   DCHECK(IsWritePending());
214   std::unique_ptr<ReadOnlyBuffer> pending_write_buffer =
215       std::move(pending_write_buffer_);
216   if (error == mojom::SerialSendError::NONE) {
217     pending_write_buffer->Done(bytes_written);
218   } else {
219     pending_write_buffer->DoneWithError(bytes_written,
220                                         static_cast<int32_t>(error));
221   }
222   Release();
223 }
224
225 bool SerialIoHandler::IsReadPending() const {
226   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
227   return pending_read_buffer_ != NULL;
228 }
229
230 bool SerialIoHandler::IsWritePending() const {
231   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
232   return pending_write_buffer_ != NULL;
233 }
234
235 void SerialIoHandler::CancelRead(mojom::SerialReceiveError reason) {
236   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
237   if (IsReadPending() && !read_canceled_) {
238     read_canceled_ = true;
239     read_cancel_reason_ = reason;
240     CancelReadImpl();
241   }
242 }
243
244 void SerialIoHandler::CancelWrite(mojom::SerialSendError reason) {
245   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
246   if (IsWritePending() && !write_canceled_) {
247     write_canceled_ = true;
248     write_cancel_reason_ = reason;
249     CancelWriteImpl();
250   }
251 }
252
253 bool SerialIoHandler::ConfigurePort(
254     const mojom::SerialConnectionOptions& options) {
255   MergeConnectionOptions(options);
256   return ConfigurePortImpl();
257 }
258
259 void SerialIoHandler::QueueReadCompleted(int bytes_read,
260                                          mojom::SerialReceiveError error) {
261   base::ThreadTaskRunnerHandle::Get()->PostTask(
262       FROM_HERE,
263       base::BindOnce(&SerialIoHandler::ReadCompleted, this, bytes_read, error));
264 }
265
266 void SerialIoHandler::QueueWriteCompleted(int bytes_written,
267                                           mojom::SerialSendError error) {
268   base::ThreadTaskRunnerHandle::Get()->PostTask(
269       FROM_HERE, base::BindOnce(&SerialIoHandler::WriteCompleted, this,
270                                 bytes_written, error));
271 }
272
273 }  // namespace device