| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "device/serial/serial_io_handler_posix.h" | 5 #include "device/serial/serial_io_handler_posix.h" |
| 6 | 6 |
| 7 #include <sys/ioctl.h> | 7 #include <sys/ioctl.h> |
| 8 #include <termios.h> | 8 #include <termios.h> |
| 9 | 9 |
| 10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 | 113 |
| 114 // static | 114 // static |
| 115 scoped_refptr<SerialIoHandler> SerialIoHandler::Create( | 115 scoped_refptr<SerialIoHandler> SerialIoHandler::Create( |
| 116 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, | 116 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, |
| 117 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) { | 117 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) { |
| 118 return new SerialIoHandlerPosix(file_thread_task_runner, | 118 return new SerialIoHandlerPosix(file_thread_task_runner, |
| 119 ui_thread_task_runner); | 119 ui_thread_task_runner); |
| 120 } | 120 } |
| 121 | 121 |
| 122 void SerialIoHandlerPosix::ReadImpl() { | 122 void SerialIoHandlerPosix::ReadImpl() { |
| 123 DCHECK(CalledOnValidThread()); | 123 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 124 DCHECK(pending_read_buffer()); | 124 DCHECK(pending_read_buffer()); |
| 125 DCHECK(file().IsValid()); | 125 DCHECK(file().IsValid()); |
| 126 | 126 |
| 127 // Try to read immediately. This is needed because on some platforms | 127 // Try to read immediately. This is needed because on some platforms |
| 128 // (e.g., OSX) there may not be a notification from the message loop | 128 // (e.g., OSX) there may not be a notification from the message loop |
| 129 // when the fd is ready to read immediately after it is opened. There | 129 // when the fd is ready to read immediately after it is opened. There |
| 130 // is no danger of blocking because the fd is opened with async flag. | 130 // is no danger of blocking because the fd is opened with async flag. |
| 131 AttemptRead(true); | 131 AttemptRead(true); |
| 132 } | 132 } |
| 133 | 133 |
| 134 void SerialIoHandlerPosix::WriteImpl() { | 134 void SerialIoHandlerPosix::WriteImpl() { |
| 135 DCHECK(CalledOnValidThread()); | 135 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 136 DCHECK(pending_write_buffer()); | 136 DCHECK(pending_write_buffer()); |
| 137 DCHECK(file().IsValid()); | 137 DCHECK(file().IsValid()); |
| 138 | 138 |
| 139 EnsureWatchingWrites(); | 139 EnsureWatchingWrites(); |
| 140 } | 140 } |
| 141 | 141 |
| 142 void SerialIoHandlerPosix::CancelReadImpl() { | 142 void SerialIoHandlerPosix::CancelReadImpl() { |
| 143 DCHECK(CalledOnValidThread()); | 143 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 144 file_read_watcher_.reset(); | 144 file_read_watcher_.reset(); |
| 145 QueueReadCompleted(0, read_cancel_reason()); | 145 QueueReadCompleted(0, read_cancel_reason()); |
| 146 } | 146 } |
| 147 | 147 |
| 148 void SerialIoHandlerPosix::CancelWriteImpl() { | 148 void SerialIoHandlerPosix::CancelWriteImpl() { |
| 149 DCHECK(CalledOnValidThread()); | 149 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 150 file_write_watcher_.reset(); | 150 file_write_watcher_.reset(); |
| 151 QueueWriteCompleted(0, write_cancel_reason()); | 151 QueueWriteCompleted(0, write_cancel_reason()); |
| 152 } | 152 } |
| 153 | 153 |
| 154 bool SerialIoHandlerPosix::ConfigurePortImpl() { | 154 bool SerialIoHandlerPosix::ConfigurePortImpl() { |
| 155 #if defined(OS_LINUX) | 155 #if defined(OS_LINUX) |
| 156 struct termios2 config; | 156 struct termios2 config; |
| 157 if (ioctl(file().GetPlatformFile(), TCGETS2, &config) < 0) { | 157 if (ioctl(file().GetPlatformFile(), TCGETS2, &config) < 0) { |
| 158 #else | 158 #else |
| 159 struct termios config; | 159 struct termios config; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 | 293 |
| 294 SerialIoHandlerPosix::SerialIoHandlerPosix( | 294 SerialIoHandlerPosix::SerialIoHandlerPosix( |
| 295 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, | 295 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, |
| 296 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) | 296 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) |
| 297 : SerialIoHandler(file_thread_task_runner, ui_thread_task_runner) {} | 297 : SerialIoHandler(file_thread_task_runner, ui_thread_task_runner) {} |
| 298 | 298 |
| 299 SerialIoHandlerPosix::~SerialIoHandlerPosix() { | 299 SerialIoHandlerPosix::~SerialIoHandlerPosix() { |
| 300 } | 300 } |
| 301 | 301 |
| 302 void SerialIoHandlerPosix::AttemptRead(bool within_read) { | 302 void SerialIoHandlerPosix::AttemptRead(bool within_read) { |
| 303 DCHECK(CalledOnValidThread()); | 303 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 304 | 304 |
| 305 if (pending_read_buffer()) { | 305 if (pending_read_buffer()) { |
| 306 int bytes_read = HANDLE_EINTR(read(file().GetPlatformFile(), | 306 int bytes_read = HANDLE_EINTR(read(file().GetPlatformFile(), |
| 307 pending_read_buffer(), | 307 pending_read_buffer(), |
| 308 pending_read_buffer_len())); | 308 pending_read_buffer_len())); |
| 309 if (bytes_read < 0) { | 309 if (bytes_read < 0) { |
| 310 if (errno == EAGAIN) { | 310 if (errno == EAGAIN) { |
| 311 // The fd does not have data to read yet so continue waiting. | 311 // The fd does not have data to read yet so continue waiting. |
| 312 EnsureWatchingReads(); | 312 EnsureWatchingReads(); |
| 313 } else if (errno == ENXIO) { | 313 } else if (errno == ENXIO) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 // completes and releases the pending_read_buffer. | 350 // completes and releases the pending_read_buffer. |
| 351 file_read_watcher_.reset(); | 351 file_read_watcher_.reset(); |
| 352 | 352 |
| 353 QueueReadCompleted(bytes_read, error); | 353 QueueReadCompleted(bytes_read, error); |
| 354 } else { | 354 } else { |
| 355 ReadCompleted(bytes_read, error); | 355 ReadCompleted(bytes_read, error); |
| 356 } | 356 } |
| 357 } | 357 } |
| 358 | 358 |
| 359 void SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking() { | 359 void SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking() { |
| 360 DCHECK(CalledOnValidThread()); | 360 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 361 | 361 |
| 362 if (pending_write_buffer()) { | 362 if (pending_write_buffer()) { |
| 363 int bytes_written = HANDLE_EINTR(write(file().GetPlatformFile(), | 363 int bytes_written = HANDLE_EINTR(write(file().GetPlatformFile(), |
| 364 pending_write_buffer(), | 364 pending_write_buffer(), |
| 365 pending_write_buffer_len())); | 365 pending_write_buffer_len())); |
| 366 if (bytes_written < 0) { | 366 if (bytes_written < 0) { |
| 367 WriteCompleted(0, serial::SendError::SYSTEM_ERROR); | 367 WriteCompleted(0, serial::SendError::SYSTEM_ERROR); |
| 368 } else { | 368 } else { |
| 369 WriteCompleted(bytes_written, serial::SendError::NONE); | 369 WriteCompleted(bytes_written, serial::SendError::NONE); |
| 370 } | 370 } |
| 371 } else { | 371 } else { |
| 372 // Stop watching the fd if we get notifications with no pending | 372 // Stop watching the fd if we get notifications with no pending |
| 373 // writes to avoid starving the message loop. | 373 // writes to avoid starving the message loop. |
| 374 file_write_watcher_.reset(); | 374 file_write_watcher_.reset(); |
| 375 } | 375 } |
| 376 } | 376 } |
| 377 | 377 |
| 378 void SerialIoHandlerPosix::EnsureWatchingReads() { | 378 void SerialIoHandlerPosix::EnsureWatchingReads() { |
| 379 DCHECK(CalledOnValidThread()); | 379 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 380 DCHECK(file().IsValid()); | 380 DCHECK(file().IsValid()); |
| 381 if (!file_read_watcher_) { | 381 if (!file_read_watcher_) { |
| 382 file_read_watcher_ = base::FileDescriptorWatcher::WatchReadable( | 382 file_read_watcher_ = base::FileDescriptorWatcher::WatchReadable( |
| 383 file().GetPlatformFile(), base::Bind(&SerialIoHandlerPosix::AttemptRead, | 383 file().GetPlatformFile(), base::Bind(&SerialIoHandlerPosix::AttemptRead, |
| 384 base::Unretained(this), false)); | 384 base::Unretained(this), false)); |
| 385 } | 385 } |
| 386 } | 386 } |
| 387 | 387 |
| 388 void SerialIoHandlerPosix::EnsureWatchingWrites() { | 388 void SerialIoHandlerPosix::EnsureWatchingWrites() { |
| 389 DCHECK(CalledOnValidThread()); | 389 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 390 DCHECK(file().IsValid()); | 390 DCHECK(file().IsValid()); |
| 391 if (!file_write_watcher_) { | 391 if (!file_write_watcher_) { |
| 392 file_write_watcher_ = base::FileDescriptorWatcher::WatchWritable( | 392 file_write_watcher_ = base::FileDescriptorWatcher::WatchWritable( |
| 393 file().GetPlatformFile(), | 393 file().GetPlatformFile(), |
| 394 base::Bind(&SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking, | 394 base::Bind(&SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking, |
| 395 base::Unretained(this))); | 395 base::Unretained(this))); |
| 396 } | 396 } |
| 397 } | 397 } |
| 398 | 398 |
| 399 bool SerialIoHandlerPosix::Flush() const { | 399 bool SerialIoHandlerPosix::Flush() const { |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 memcpy(buffer, chars_stashed_, std::min(new_bytes_read, 2)); | 631 memcpy(buffer, chars_stashed_, std::min(new_bytes_read, 2)); |
| 632 memcpy(chars_stashed_, tmp, num_chars_stashed_); | 632 memcpy(chars_stashed_, tmp, num_chars_stashed_); |
| 633 return new_bytes_read; | 633 return new_bytes_read; |
| 634 } | 634 } |
| 635 | 635 |
| 636 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) { | 636 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) { |
| 637 return port_name; | 637 return port_name; |
| 638 } | 638 } |
| 639 | 639 |
| 640 } // namespace device | 640 } // namespace device |
| OLD | NEW |