• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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 "chrome/browser/extensions/api/serial/serial_io_handler_posix.h"
6 
7 #include "base/posix/eintr_wrapper.h"
8 
9 namespace {
10 const base::PlatformFile kInvalidPlatformFileValue = -1;
11 }  // namespace
12 
13 namespace extensions {
14 
15 // static
Create()16 scoped_refptr<SerialIoHandler> SerialIoHandler::Create() {
17   return new SerialIoHandlerPosix();
18 }
19 
ReadImpl()20 void SerialIoHandlerPosix::ReadImpl() {
21   DCHECK(CalledOnValidThread());
22   DCHECK(pending_read_buffer());
23   DCHECK_NE(file(), kInvalidPlatformFileValue);
24 
25   EnsureWatchingReads();
26 }
27 
WriteImpl()28 void SerialIoHandlerPosix::WriteImpl() {
29   DCHECK(CalledOnValidThread());
30   DCHECK(pending_write_buffer());
31   DCHECK_NE(file(), kInvalidPlatformFileValue);
32 
33   EnsureWatchingWrites();
34 }
35 
CancelReadImpl()36 void SerialIoHandlerPosix::CancelReadImpl() {
37   DCHECK(CalledOnValidThread());
38   is_watching_reads_ = false;
39   file_read_watcher_.StopWatchingFileDescriptor();
40   QueueReadCompleted(0, read_cancel_reason());
41 }
42 
CancelWriteImpl()43 void SerialIoHandlerPosix::CancelWriteImpl() {
44   DCHECK(CalledOnValidThread());
45   is_watching_writes_ = false;
46   file_write_watcher_.StopWatchingFileDescriptor();
47   QueueWriteCompleted(0, write_cancel_reason());
48 }
49 
SerialIoHandlerPosix()50 SerialIoHandlerPosix::SerialIoHandlerPosix()
51     : is_watching_reads_(false),
52       is_watching_writes_(false) {
53 }
54 
~SerialIoHandlerPosix()55 SerialIoHandlerPosix::~SerialIoHandlerPosix() {}
56 
OnFileCanReadWithoutBlocking(int fd)57 void SerialIoHandlerPosix::OnFileCanReadWithoutBlocking(int fd) {
58   DCHECK(CalledOnValidThread());
59   DCHECK_EQ(fd, file());
60 
61   if (pending_read_buffer()) {
62     int bytes_read = HANDLE_EINTR(read(file(),
63                                        pending_read_buffer()->data(),
64                                        pending_read_buffer_len()));
65     if (bytes_read < 0) {
66       if (errno == ENXIO) {
67         ReadCompleted(0, api::serial::RECEIVE_ERROR_DEVICE_LOST);
68       } else {
69         ReadCompleted(0, api::serial::RECEIVE_ERROR_SYSTEM_ERROR);
70       }
71     } else if (bytes_read == 0) {
72       ReadCompleted(0, api::serial::RECEIVE_ERROR_DEVICE_LOST);
73     } else {
74       ReadCompleted(bytes_read, api::serial::RECEIVE_ERROR_NONE);
75     }
76   } else {
77     // Stop watching the fd if we get notifications with no pending
78     // reads or writes to avoid starving the message loop.
79     is_watching_reads_ = false;
80     file_read_watcher_.StopWatchingFileDescriptor();
81   }
82 }
83 
OnFileCanWriteWithoutBlocking(int fd)84 void SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking(int fd) {
85   DCHECK(CalledOnValidThread());
86   DCHECK_EQ(fd, file());
87 
88   if (pending_write_buffer()) {
89     int bytes_written = HANDLE_EINTR(write(file(),
90                                            pending_write_buffer()->data(),
91                                            pending_write_buffer_len()));
92     if (bytes_written < 0) {
93       WriteCompleted(0, api::serial::SEND_ERROR_SYSTEM_ERROR);
94     } else {
95       WriteCompleted(bytes_written, api::serial::SEND_ERROR_NONE);
96     }
97   } else {
98     // Stop watching the fd if we get notifications with no pending
99     // writes to avoid starving the message loop.
100     is_watching_writes_ = false;
101     file_write_watcher_.StopWatchingFileDescriptor();
102   }
103 }
104 
EnsureWatchingReads()105 void SerialIoHandlerPosix::EnsureWatchingReads() {
106   DCHECK(CalledOnValidThread());
107   DCHECK_NE(file(), kInvalidPlatformFileValue);
108   if (!is_watching_reads_) {
109     is_watching_reads_ = base::MessageLoopForIO::current()->WatchFileDescriptor(
110         file(), true, base::MessageLoopForIO::WATCH_READ,
111         &file_read_watcher_, this);
112   }
113 }
114 
EnsureWatchingWrites()115 void SerialIoHandlerPosix::EnsureWatchingWrites() {
116   DCHECK(CalledOnValidThread());
117   DCHECK_NE(file(), kInvalidPlatformFileValue);
118   if (!is_watching_writes_) {
119     is_watching_writes_ =
120         base::MessageLoopForIO::current()->WatchFileDescriptor(
121             file(), true, base::MessageLoopForIO::WATCH_WRITE,
122             &file_write_watcher_, this);
123   }
124 }
125 
126 }  // namespace extensions
127