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