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