| 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/posix/eintr_wrapper.h" | 10 #include "base/posix/eintr_wrapper.h" |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 void SerialIoHandlerPosix::WriteImpl() { | 133 void SerialIoHandlerPosix::WriteImpl() { |
| 134 DCHECK(CalledOnValidThread()); | 134 DCHECK(CalledOnValidThread()); |
| 135 DCHECK(pending_write_buffer()); | 135 DCHECK(pending_write_buffer()); |
| 136 DCHECK(file().IsValid()); | 136 DCHECK(file().IsValid()); |
| 137 | 137 |
| 138 EnsureWatchingWrites(); | 138 EnsureWatchingWrites(); |
| 139 } | 139 } |
| 140 | 140 |
| 141 void SerialIoHandlerPosix::CancelReadImpl() { | 141 void SerialIoHandlerPosix::CancelReadImpl() { |
| 142 DCHECK(CalledOnValidThread()); | 142 DCHECK(CalledOnValidThread()); |
| 143 is_watching_reads_ = false; | 143 file_read_watcher_.reset(); |
| 144 file_read_watcher_.StopWatchingFileDescriptor(); | |
| 145 QueueReadCompleted(0, read_cancel_reason()); | 144 QueueReadCompleted(0, read_cancel_reason()); |
| 146 } | 145 } |
| 147 | 146 |
| 148 void SerialIoHandlerPosix::CancelWriteImpl() { | 147 void SerialIoHandlerPosix::CancelWriteImpl() { |
| 149 DCHECK(CalledOnValidThread()); | 148 DCHECK(CalledOnValidThread()); |
| 150 is_watching_writes_ = false; | 149 file_write_watcher_.reset(); |
| 151 file_write_watcher_.StopWatchingFileDescriptor(); | |
| 152 QueueWriteCompleted(0, write_cancel_reason()); | 150 QueueWriteCompleted(0, write_cancel_reason()); |
| 153 } | 151 } |
| 154 | 152 |
| 155 bool SerialIoHandlerPosix::ConfigurePortImpl() { | 153 bool SerialIoHandlerPosix::ConfigurePortImpl() { |
| 156 #if defined(OS_LINUX) | 154 #if defined(OS_LINUX) |
| 157 struct termios2 config; | 155 struct termios2 config; |
| 158 if (ioctl(file().GetPlatformFile(), TCGETS2, &config) < 0) { | 156 if (ioctl(file().GetPlatformFile(), TCGETS2, &config) < 0) { |
| 159 #else | 157 #else |
| 160 struct termios config; | 158 struct termios config; |
| 161 if (tcgetattr(file().GetPlatformFile(), &config) != 0) { | 159 if (tcgetattr(file().GetPlatformFile(), &config) != 0) { |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 } | 277 } |
| 280 } | 278 } |
| 281 #endif | 279 #endif |
| 282 | 280 |
| 283 return true; | 281 return true; |
| 284 } | 282 } |
| 285 | 283 |
| 286 SerialIoHandlerPosix::SerialIoHandlerPosix( | 284 SerialIoHandlerPosix::SerialIoHandlerPosix( |
| 287 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, | 285 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, |
| 288 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) | 286 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) |
| 289 : SerialIoHandler(file_thread_task_runner, ui_thread_task_runner), | 287 : SerialIoHandler(file_thread_task_runner, ui_thread_task_runner) {} |
| 290 is_watching_reads_(false), | |
| 291 is_watching_writes_(false) { | |
| 292 } | |
| 293 | 288 |
| 294 SerialIoHandlerPosix::~SerialIoHandlerPosix() { | 289 SerialIoHandlerPosix::~SerialIoHandlerPosix() { |
| 295 } | 290 } |
| 296 | 291 |
| 297 void SerialIoHandlerPosix::OnFileCanReadWithoutBlocking(int fd) { | 292 void SerialIoHandlerPosix::AttemptRead(bool within_read) { |
| 298 DCHECK(CalledOnValidThread()); | 293 DCHECK(CalledOnValidThread()); |
| 299 DCHECK_EQ(fd, file().GetPlatformFile()); | |
| 300 | 294 |
| 301 AttemptRead(false); | |
| 302 } | |
| 303 | |
| 304 bool SerialIoHandlerPosix::AttemptRead(bool within_read) { | |
| 305 if (pending_read_buffer()) { | 295 if (pending_read_buffer()) { |
| 306 int bytes_read = HANDLE_EINTR(read(file().GetPlatformFile(), | 296 int bytes_read = HANDLE_EINTR(read(file().GetPlatformFile(), |
| 307 pending_read_buffer(), | 297 pending_read_buffer(), |
| 308 pending_read_buffer_len())); | 298 pending_read_buffer_len())); |
| 309 if (bytes_read < 0) { | 299 if (bytes_read < 0) { |
| 310 if (errno == EAGAIN) { | 300 if (errno == EAGAIN) { |
| 311 // The fd does not have data to read yet so continue waiting. | 301 // The fd does not have data to read yet so continue waiting. |
| 312 EnsureWatchingReads(); | 302 EnsureWatchingReads(); |
| 313 } else if (errno == ENXIO) { | 303 } else if (errno == ENXIO) { |
| 314 RunReadCompleted(within_read, 0, serial::ReceiveError::DEVICE_LOST); | 304 RunReadCompleted(within_read, 0, serial::ReceiveError::DEVICE_LOST); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 331 RunReadCompleted(within_read, new_bytes_read, | 321 RunReadCompleted(within_read, new_bytes_read, |
| 332 serial::ReceiveError::PARITY_ERROR); | 322 serial::ReceiveError::PARITY_ERROR); |
| 333 } else { | 323 } else { |
| 334 RunReadCompleted(within_read, new_bytes_read, | 324 RunReadCompleted(within_read, new_bytes_read, |
| 335 serial::ReceiveError::NONE); | 325 serial::ReceiveError::NONE); |
| 336 } | 326 } |
| 337 } | 327 } |
| 338 } else { | 328 } else { |
| 339 // Stop watching the fd if we get notifications with no pending | 329 // Stop watching the fd if we get notifications with no pending |
| 340 // reads or writes to avoid starving the message loop. | 330 // reads or writes to avoid starving the message loop. |
| 341 is_watching_reads_ = false; | 331 file_read_watcher_.reset(); |
| 342 file_read_watcher_.StopWatchingFileDescriptor(); | |
| 343 } | 332 } |
| 344 | |
| 345 return true; | |
| 346 } | 333 } |
| 347 | 334 |
| 348 void SerialIoHandlerPosix::RunReadCompleted(bool within_read, | 335 void SerialIoHandlerPosix::RunReadCompleted(bool within_read, |
| 349 int bytes_read, | 336 int bytes_read, |
| 350 serial::ReceiveError error) { | 337 serial::ReceiveError error) { |
| 351 if (within_read) { | 338 if (within_read) { |
| 352 // Stop watching the fd to avoid more reads until the queued ReadCompleted() | 339 // Stop watching the fd to avoid more reads until the queued ReadCompleted() |
| 353 // completes and releases the pending_read_buffer. | 340 // completes and releases the pending_read_buffer. |
| 354 is_watching_reads_ = false; | 341 file_read_watcher_.reset(); |
| 355 file_read_watcher_.StopWatchingFileDescriptor(); | |
| 356 | 342 |
| 357 QueueReadCompleted(bytes_read, error); | 343 QueueReadCompleted(bytes_read, error); |
| 358 } else { | 344 } else { |
| 359 ReadCompleted(bytes_read, error); | 345 ReadCompleted(bytes_read, error); |
| 360 } | 346 } |
| 361 } | 347 } |
| 362 | 348 |
| 363 void SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking(int fd) { | 349 void SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking() { |
| 364 DCHECK(CalledOnValidThread()); | 350 DCHECK(CalledOnValidThread()); |
| 365 DCHECK_EQ(fd, file().GetPlatformFile()); | |
| 366 | 351 |
| 367 if (pending_write_buffer()) { | 352 if (pending_write_buffer()) { |
| 368 int bytes_written = HANDLE_EINTR(write(file().GetPlatformFile(), | 353 int bytes_written = HANDLE_EINTR(write(file().GetPlatformFile(), |
| 369 pending_write_buffer(), | 354 pending_write_buffer(), |
| 370 pending_write_buffer_len())); | 355 pending_write_buffer_len())); |
| 371 if (bytes_written < 0) { | 356 if (bytes_written < 0) { |
| 372 WriteCompleted(0, serial::SendError::SYSTEM_ERROR); | 357 WriteCompleted(0, serial::SendError::SYSTEM_ERROR); |
| 373 } else { | 358 } else { |
| 374 WriteCompleted(bytes_written, serial::SendError::NONE); | 359 WriteCompleted(bytes_written, serial::SendError::NONE); |
| 375 } | 360 } |
| 376 } else { | 361 } else { |
| 377 // Stop watching the fd if we get notifications with no pending | 362 // Stop watching the fd if we get notifications with no pending |
| 378 // writes to avoid starving the message loop. | 363 // writes to avoid starving the message loop. |
| 379 is_watching_writes_ = false; | 364 file_write_watcher_.reset(); |
| 380 file_write_watcher_.StopWatchingFileDescriptor(); | |
| 381 } | 365 } |
| 382 } | 366 } |
| 383 | 367 |
| 384 void SerialIoHandlerPosix::EnsureWatchingReads() { | 368 void SerialIoHandlerPosix::EnsureWatchingReads() { |
| 385 DCHECK(CalledOnValidThread()); | 369 DCHECK(CalledOnValidThread()); |
| 386 DCHECK(file().IsValid()); | 370 DCHECK(file().IsValid()); |
| 387 if (!is_watching_reads_) { | 371 if (!file_read_watcher_) { |
| 388 is_watching_reads_ = base::MessageLoopForIO::current()->WatchFileDescriptor( | 372 file_read_watcher_ = base::FileDescriptorWatcher::WatchReadable( |
| 389 file().GetPlatformFile(), | 373 file().GetPlatformFile(), base::Bind(&SerialIoHandlerPosix::AttemptRead, |
| 390 true, | 374 base::Unretained(this), false)); |
| 391 base::MessageLoopForIO::WATCH_READ, | |
| 392 &file_read_watcher_, | |
| 393 this); | |
| 394 } | 375 } |
| 395 } | 376 } |
| 396 | 377 |
| 397 void SerialIoHandlerPosix::EnsureWatchingWrites() { | 378 void SerialIoHandlerPosix::EnsureWatchingWrites() { |
| 398 DCHECK(CalledOnValidThread()); | 379 DCHECK(CalledOnValidThread()); |
| 399 DCHECK(file().IsValid()); | 380 DCHECK(file().IsValid()); |
| 400 if (!is_watching_writes_) { | 381 if (!file_write_watcher_) { |
| 401 is_watching_writes_ = | 382 file_write_watcher_ = base::FileDescriptorWatcher::WatchWritable( |
| 402 base::MessageLoopForIO::current()->WatchFileDescriptor( | 383 file().GetPlatformFile(), |
| 403 file().GetPlatformFile(), | 384 base::Bind(&SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking, |
| 404 true, | 385 base::Unretained(this))); |
| 405 base::MessageLoopForIO::WATCH_WRITE, | |
| 406 &file_write_watcher_, | |
| 407 this); | |
| 408 } | 386 } |
| 409 } | 387 } |
| 410 | 388 |
| 411 bool SerialIoHandlerPosix::Flush() const { | 389 bool SerialIoHandlerPosix::Flush() const { |
| 412 if (tcflush(file().GetPlatformFile(), TCIOFLUSH) != 0) { | 390 if (tcflush(file().GetPlatformFile(), TCIOFLUSH) != 0) { |
| 413 VPLOG(1) << "Failed to flush port"; | 391 VPLOG(1) << "Failed to flush port"; |
| 414 return false; | 392 return false; |
| 415 } | 393 } |
| 416 return true; | 394 return true; |
| 417 } | 395 } |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 643 memcpy(buffer, chars_stashed_, std::min(new_bytes_read, 2)); | 621 memcpy(buffer, chars_stashed_, std::min(new_bytes_read, 2)); |
| 644 memcpy(chars_stashed_, tmp, num_chars_stashed_); | 622 memcpy(chars_stashed_, tmp, num_chars_stashed_); |
| 645 return new_bytes_read; | 623 return new_bytes_read; |
| 646 } | 624 } |
| 647 | 625 |
| 648 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) { | 626 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) { |
| 649 return port_name; | 627 return port_name; |
| 650 } | 628 } |
| 651 | 629 |
| 652 } // namespace device | 630 } // namespace device |
| OLD | NEW |