Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "tools/battor_agent/battor_connection_impl.h" | 5 #include "tools/battor_agent/battor_connection_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/command_line.h" | |
| 9 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| 10 #include "base/thread_task_runner_handle.h" | 11 #include "base/thread_task_runner_handle.h" |
| 11 #include "device/serial/buffer.h" | 12 #include "device/serial/buffer.h" |
| 12 #include "device/serial/serial_io_handler.h" | 13 #include "device/serial/serial_io_handler.h" |
| 13 #include "net/base/io_buffer.h" | 14 #include "net/base/io_buffer.h" |
| 15 #include "tools/battor_agent/serial_utils.h" | |
| 14 | 16 |
| 17 using std::endl; | |
| 15 using std::vector; | 18 using std::vector; |
| 16 | 19 |
| 17 namespace battor { | 20 namespace battor { |
| 18 | 21 |
| 19 namespace { | 22 namespace { |
| 20 | 23 |
| 24 // The command line switch used to specify a file to which serial communication | |
| 25 // is logged. | |
| 26 const char kSerialLogPathSwitch[] = "battor-serial-log"; | |
| 27 | |
| 21 // Serial configuration parameters for the BattOr. | 28 // Serial configuration parameters for the BattOr. |
| 22 const uint32_t kBattOrBitrate = 2000000; | 29 const uint32_t kBattOrBitrate = 2000000; |
| 23 const device::serial::DataBits kBattOrDataBits = | 30 const device::serial::DataBits kBattOrDataBits = |
| 24 device::serial::DataBits::EIGHT; | 31 device::serial::DataBits::EIGHT; |
| 25 const device::serial::ParityBit kBattOrParityBit = | 32 const device::serial::ParityBit kBattOrParityBit = |
| 26 device::serial::ParityBit::NONE; | 33 device::serial::ParityBit::NONE; |
| 27 const device::serial::StopBits kBattOrStopBit = device::serial::StopBits::ONE; | 34 const device::serial::StopBits kBattOrStopBit = device::serial::StopBits::ONE; |
| 28 const bool kBattOrCtsFlowControl = true; | 35 const bool kBattOrCtsFlowControl = true; |
| 29 const bool kBattOrHasCtsFlowControl = true; | 36 const bool kBattOrHasCtsFlowControl = true; |
| 30 // The maximum BattOr message is 50kB long. | 37 // The maximum BattOr message is 50kB long. |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 51 } // namespace | 58 } // namespace |
| 52 | 59 |
| 53 BattOrConnectionImpl::BattOrConnectionImpl( | 60 BattOrConnectionImpl::BattOrConnectionImpl( |
| 54 const std::string& path, | 61 const std::string& path, |
| 55 BattOrConnection::Listener* listener, | 62 BattOrConnection::Listener* listener, |
| 56 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, | 63 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, |
| 57 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) | 64 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) |
| 58 : BattOrConnection(listener), | 65 : BattOrConnection(listener), |
| 59 path_(path), | 66 path_(path), |
| 60 file_thread_task_runner_(file_thread_task_runner), | 67 file_thread_task_runner_(file_thread_task_runner), |
| 61 ui_thread_task_runner_(ui_thread_task_runner) {} | 68 ui_thread_task_runner_(ui_thread_task_runner) { |
| 69 std::string serial_log_path = | |
| 70 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
| 71 kSerialLogPathSwitch); | |
| 72 if (!serial_log_path.empty()) { | |
| 73 serial_log_.open(serial_log_path.c_str(), | |
| 74 std::fstream::out | std::fstream::trunc); | |
| 75 serial_log_ << std::boolalpha; | |
| 76 } | |
| 77 } | |
| 62 | 78 |
| 63 BattOrConnectionImpl::~BattOrConnectionImpl() {} | 79 BattOrConnectionImpl::~BattOrConnectionImpl() {} |
| 64 | 80 |
| 65 void BattOrConnectionImpl::Open() { | 81 void BattOrConnectionImpl::Open() { |
| 66 if (io_handler_) { | 82 if (io_handler_) { |
| 67 OnOpened(true); | 83 OnOpened(true); |
| 68 return; | 84 return; |
| 69 } | 85 } |
| 70 | 86 |
| 71 io_handler_ = CreateIoHandler(); | 87 io_handler_ = CreateIoHandler(); |
| 72 | 88 |
| 73 device::serial::ConnectionOptions options; | 89 device::serial::ConnectionOptions options; |
| 74 options.bitrate = kBattOrBitrate; | 90 options.bitrate = kBattOrBitrate; |
| 75 options.data_bits = kBattOrDataBits; | 91 options.data_bits = kBattOrDataBits; |
| 76 options.parity_bit = kBattOrParityBit; | 92 options.parity_bit = kBattOrParityBit; |
| 77 options.stop_bits = kBattOrStopBit; | 93 options.stop_bits = kBattOrStopBit; |
| 78 options.cts_flow_control = kBattOrCtsFlowControl; | 94 options.cts_flow_control = kBattOrCtsFlowControl; |
| 79 options.has_cts_flow_control = kBattOrHasCtsFlowControl; | 95 options.has_cts_flow_control = kBattOrHasCtsFlowControl; |
| 80 | 96 |
| 97 serial_log_ << "Opening serial connection." << endl << endl; | |
| 81 io_handler_->Open(path_, options, | 98 io_handler_->Open(path_, options, |
| 82 base::Bind(&BattOrConnectionImpl::OnOpened, AsWeakPtr())); | 99 base::Bind(&BattOrConnectionImpl::OnOpened, AsWeakPtr())); |
| 83 } | 100 } |
| 84 | 101 |
| 85 void BattOrConnectionImpl::OnOpened(bool success) { | 102 void BattOrConnectionImpl::OnOpened(bool success) { |
| 103 serial_log_ << "Serial connection open finished with success: " << success | |
| 104 << "." << endl | |
| 105 << endl; | |
| 106 | |
| 86 if (!success) | 107 if (!success) |
| 87 Close(); | 108 Close(); |
| 88 | 109 |
| 89 base::ThreadTaskRunnerHandle::Get()->PostTask( | 110 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 90 FROM_HERE, base::Bind(&Listener::OnConnectionOpened, | 111 FROM_HERE, base::Bind(&Listener::OnConnectionOpened, |
| 91 base::Unretained(listener_), success)); | 112 base::Unretained(listener_), success)); |
| 92 } | 113 } |
| 93 | 114 |
| 94 void BattOrConnectionImpl::Close() { | 115 void BattOrConnectionImpl::Close() { |
| 116 serial_log_ << "Serial connection closed." << endl << endl; | |
| 95 io_handler_ = nullptr; | 117 io_handler_ = nullptr; |
| 96 } | 118 } |
| 97 | 119 |
| 98 void BattOrConnectionImpl::SendBytes(BattOrMessageType type, | 120 void BattOrConnectionImpl::SendBytes(BattOrMessageType type, |
| 99 const void* buffer, | 121 const void* buffer, |
| 100 size_t bytes_to_send) { | 122 size_t bytes_to_send) { |
| 101 const char* bytes = reinterpret_cast<const char*>(buffer); | 123 const char* bytes = reinterpret_cast<const char*>(buffer); |
| 102 | 124 |
| 103 // Reserve a send buffer with enough extra bytes for the start, type, end, and | 125 // Reserve a send buffer with enough extra bytes for the start, type, end, and |
| 104 // escape bytes. | 126 // escape bytes. |
| 105 vector<char> data; | 127 vector<char> data; |
| 106 data.reserve(2 * bytes_to_send + 3); | 128 data.reserve(2 * bytes_to_send + 3); |
| 107 | 129 |
| 108 data.push_back(BATTOR_CONTROL_BYTE_START); | 130 data.push_back(BATTOR_CONTROL_BYTE_START); |
| 109 data.push_back(type); | 131 data.push_back(type); |
| 110 | 132 |
| 111 for (size_t i = 0; i < bytes_to_send; i++) { | 133 for (size_t i = 0; i < bytes_to_send; i++) { |
| 112 if (bytes[i] == BATTOR_CONTROL_BYTE_START || | 134 if (bytes[i] == BATTOR_CONTROL_BYTE_START || |
| 113 bytes[i] == BATTOR_CONTROL_BYTE_END) { | 135 bytes[i] == BATTOR_CONTROL_BYTE_END) { |
| 114 data.push_back(BATTOR_CONTROL_BYTE_ESCAPE); | 136 data.push_back(BATTOR_CONTROL_BYTE_ESCAPE); |
| 115 } | 137 } |
| 116 | 138 |
| 117 data.push_back(bytes[i]); | 139 data.push_back(bytes[i]); |
| 118 } | 140 } |
| 119 | 141 |
| 120 data.push_back(BATTOR_CONTROL_BYTE_END); | 142 data.push_back(BATTOR_CONTROL_BYTE_END); |
| 121 | 143 |
| 144 serial_log_ << "Bytes sent: " << CharVectorToString(data) << "." << endl | |
| 145 << endl; | |
| 146 | |
| 122 pending_write_length_ = data.size(); | 147 pending_write_length_ = data.size(); |
| 123 io_handler_->Write(base::WrapUnique(new device::SendBuffer( | 148 io_handler_->Write(base::WrapUnique(new device::SendBuffer( |
| 124 data, base::Bind(&BattOrConnectionImpl::OnBytesSent, AsWeakPtr())))); | 149 data, base::Bind(&BattOrConnectionImpl::OnBytesSent, AsWeakPtr())))); |
| 125 } | 150 } |
| 126 | 151 |
| 127 void BattOrConnectionImpl::ReadMessage(BattOrMessageType type) { | 152 void BattOrConnectionImpl::ReadMessage(BattOrMessageType type) { |
| 128 pending_read_message_type_ = type; | 153 pending_read_message_type_ = type; |
| 129 size_t max_bytes_to_read = GetMaxBytesForMessageType(type); | 154 size_t max_bytes_to_read = GetMaxBytesForMessageType(type); |
| 130 | 155 |
| 131 // Check the left-over bytes from the last read to make sure that we don't | 156 // Check the left-over bytes from the last read to make sure that we don't |
| 132 // already have a full message. | 157 // already have a full message. |
| 133 BattOrMessageType parsed_type; | 158 BattOrMessageType parsed_type; |
| 134 std::unique_ptr<vector<char>> bytes(new vector<char>()); | 159 std::unique_ptr<vector<char>> bytes(new vector<char>()); |
| 135 bytes->reserve(max_bytes_to_read); | 160 bytes->reserve(max_bytes_to_read); |
| 136 | 161 |
| 162 serial_log_ | |
| 163 << "Checking if a complete message is in the 'already read' buffer." | |
| 164 << endl | |
| 165 << endl; | |
| 166 | |
| 137 if (ParseMessage(&parsed_type, bytes.get())) { | 167 if (ParseMessage(&parsed_type, bytes.get())) { |
| 168 serial_log_ << "Complete message found." << endl << endl; | |
| 138 base::ThreadTaskRunnerHandle::Get()->PostTask( | 169 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 139 FROM_HERE, | 170 FROM_HERE, |
| 140 base::Bind(&Listener::OnMessageRead, base::Unretained(listener_), true, | 171 base::Bind(&Listener::OnMessageRead, base::Unretained(listener_), true, |
| 141 parsed_type, base::Passed(std::move(bytes)))); | 172 parsed_type, base::Passed(std::move(bytes)))); |
| 142 return; | 173 return; |
| 143 } | 174 } |
| 144 | 175 |
| 176 serial_log_ << "No complete message found." << endl << endl; | |
| 145 BeginReadBytes(max_bytes_to_read - already_read_buffer_.size()); | 177 BeginReadBytes(max_bytes_to_read - already_read_buffer_.size()); |
| 146 } | 178 } |
| 147 | 179 |
| 148 void BattOrConnectionImpl::Flush() { | 180 void BattOrConnectionImpl::Flush() { |
| 149 io_handler_->Flush(); | 181 io_handler_->Flush(); |
| 150 already_read_buffer_.clear(); | 182 already_read_buffer_.clear(); |
| 151 } | 183 } |
| 152 | 184 |
| 153 scoped_refptr<device::SerialIoHandler> BattOrConnectionImpl::CreateIoHandler() { | 185 scoped_refptr<device::SerialIoHandler> BattOrConnectionImpl::CreateIoHandler() { |
| 154 return device::SerialIoHandler::Create(file_thread_task_runner_, | 186 return device::SerialIoHandler::Create(file_thread_task_runner_, |
| 155 ui_thread_task_runner_); | 187 ui_thread_task_runner_); |
| 156 } | 188 } |
| 157 | 189 |
| 158 void BattOrConnectionImpl::BeginReadBytes(size_t max_bytes_to_read) { | 190 void BattOrConnectionImpl::BeginReadBytes(size_t max_bytes_to_read) { |
| 191 serial_log_ << "Starting read of up to " << max_bytes_to_read << " bytes." | |
| 192 << endl | |
| 193 << endl; | |
| 194 | |
| 159 pending_read_buffer_ = | 195 pending_read_buffer_ = |
| 160 make_scoped_refptr(new net::IOBuffer(max_bytes_to_read)); | 196 make_scoped_refptr(new net::IOBuffer(max_bytes_to_read)); |
| 161 | 197 |
| 162 auto on_receive_buffer_filled = | 198 auto on_receive_buffer_filled = |
| 163 base::Bind(&BattOrConnectionImpl::OnBytesRead, AsWeakPtr()); | 199 base::Bind(&BattOrConnectionImpl::OnBytesRead, AsWeakPtr()); |
| 164 | 200 |
| 165 io_handler_->Read(base::WrapUnique(new device::ReceiveBuffer( | 201 io_handler_->Read(base::WrapUnique(new device::ReceiveBuffer( |
| 166 pending_read_buffer_, static_cast<uint32_t>(max_bytes_to_read), | 202 pending_read_buffer_, static_cast<uint32_t>(max_bytes_to_read), |
| 167 on_receive_buffer_filled))); | 203 on_receive_buffer_filled))); |
| 168 } | 204 } |
| 169 | 205 |
| 170 void BattOrConnectionImpl::OnBytesRead(int bytes_read, | 206 void BattOrConnectionImpl::OnBytesRead(int bytes_read, |
| 171 device::serial::ReceiveError error) { | 207 device::serial::ReceiveError error) { |
| 172 if (bytes_read == 0 || error != device::serial::ReceiveError::NONE) { | 208 if (error != device::serial::ReceiveError::NONE) { |
| 173 // If we didn't have a message before, and we weren't able to read any | 209 serial_log_ << "Read failed with error: " << error << "." << endl << endl; |
| 174 // additional bytes, then there's no valid message available. | |
| 175 EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr); | 210 EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr); |
| 176 return; | 211 return; |
| 177 } | 212 } |
| 178 | 213 |
| 214 if (bytes_read == 0) { | |
| 215 // If we didn't have a message before, and we weren't able to read any | |
| 216 // additional bytes, then there's no valid message available. | |
| 217 serial_log_ << "Read failed due to no bytes being read." << endl << endl; | |
| 218 EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr); | |
| 219 return; | |
| 220 } | |
| 221 | |
| 222 serial_log_ << bytes_read << " more bytes read: " | |
| 223 << CharVectorToString( | |
| 224 vector<char>(pending_read_buffer_->data(), | |
| 225 pending_read_buffer_->data() + bytes_read)) | |
| 226 << "." << endl | |
| 227 << endl; | |
| 228 | |
| 179 already_read_buffer_.insert(already_read_buffer_.end(), | 229 already_read_buffer_.insert(already_read_buffer_.end(), |
| 180 pending_read_buffer_->data(), | 230 pending_read_buffer_->data(), |
| 181 pending_read_buffer_->data() + bytes_read); | 231 pending_read_buffer_->data() + bytes_read); |
| 182 | 232 |
| 183 BattOrMessageType type; | 233 BattOrMessageType type; |
| 184 std::unique_ptr<vector<char>> bytes(new vector<char>()); | 234 std::unique_ptr<vector<char>> bytes(new vector<char>()); |
| 185 bytes->reserve(GetMaxBytesForMessageType(pending_read_message_type_)); | 235 bytes->reserve(GetMaxBytesForMessageType(pending_read_message_type_)); |
| 186 | 236 |
| 187 if (!ParseMessage(&type, bytes.get())) { | 237 if (!ParseMessage(&type, bytes.get())) { |
| 188 // Even after reading the max number of bytes, we still don't have a valid | 238 serial_log_ << "Read failed due to having no complete message after max " |
| 189 // message. | 239 "read length." |
| 240 << endl | |
| 241 << endl; | |
|
nednguyen
2016/05/12 15:44:29
Let create a Log(const string& message) method ins
| |
| 190 EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr); | 242 EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr); |
| 191 return; | 243 return; |
| 192 } | 244 } |
| 193 | 245 |
| 194 if (type != pending_read_message_type_) { | 246 if (type != pending_read_message_type_) { |
| 195 // We received a complete message, but it wasn't the type we were expecting. | 247 serial_log_ << "Read failed due to receiving a message of the wrong type." |
| 248 << endl | |
| 249 << endl; | |
| 196 EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr); | 250 EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr); |
| 197 return; | 251 return; |
| 198 } | 252 } |
| 199 | 253 |
| 200 EndReadBytes(true, type, std::move(bytes)); | 254 EndReadBytes(true, type, std::move(bytes)); |
| 201 } | 255 } |
| 202 | 256 |
| 203 void BattOrConnectionImpl::EndReadBytes( | 257 void BattOrConnectionImpl::EndReadBytes(bool success, |
| 204 bool success, | 258 BattOrMessageType type, |
| 205 BattOrMessageType type, | 259 std::unique_ptr<vector<char>> bytes) { |
| 206 std::unique_ptr<std::vector<char>> bytes) { | 260 serial_log_ << "Read finished with success: " << success << "." << endl |
| 261 << endl; | |
| 262 | |
| 207 pending_read_buffer_ = nullptr; | 263 pending_read_buffer_ = nullptr; |
| 208 base::ThreadTaskRunnerHandle::Get()->PostTask( | 264 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 209 FROM_HERE, | 265 FROM_HERE, |
| 210 base::Bind(&Listener::OnMessageRead, base::Unretained(listener_), success, | 266 base::Bind(&Listener::OnMessageRead, base::Unretained(listener_), success, |
| 211 type, base::Passed(std::move(bytes)))); | 267 type, base::Passed(std::move(bytes)))); |
| 212 } | 268 } |
| 213 | 269 |
| 214 bool BattOrConnectionImpl::ParseMessage(BattOrMessageType* type, | 270 bool BattOrConnectionImpl::ParseMessage(BattOrMessageType* type, |
| 215 vector<char>* bytes) { | 271 vector<char>* bytes) { |
| 216 if (already_read_buffer_.size() <= 3) | 272 if (already_read_buffer_.size() <= 3) |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 void BattOrConnectionImpl::OnBytesSent(int bytes_sent, | 323 void BattOrConnectionImpl::OnBytesSent(int bytes_sent, |
| 268 device::serial::SendError error) { | 324 device::serial::SendError error) { |
| 269 bool success = (error == device::serial::SendError::NONE) && | 325 bool success = (error == device::serial::SendError::NONE) && |
| 270 (pending_write_length_ == static_cast<size_t>(bytes_sent)); | 326 (pending_write_length_ == static_cast<size_t>(bytes_sent)); |
| 271 base::ThreadTaskRunnerHandle::Get()->PostTask( | 327 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 272 FROM_HERE, | 328 FROM_HERE, |
| 273 base::Bind(&Listener::OnBytesSent, base::Unretained(listener_), success)); | 329 base::Bind(&Listener::OnBytesSent, base::Unretained(listener_), success)); |
| 274 } | 330 } |
| 275 | 331 |
| 276 } // namespace battor | 332 } // namespace battor |
| OLD | NEW |