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_agent.h" | 5 #include "tools/battor_agent/battor_agent.h" |
| 6 | 6 |
| 7 #include <iomanip> | 7 #include <iomanip> |
| 8 #include <iostream> | |
| 8 | 9 |
| 9 #include "base/bind.h" | 10 #include "base/bind.h" |
| 10 #include "base/threading/thread_task_runner_handle.h" | 11 #include "base/threading/thread_task_runner_handle.h" |
| 11 #include "tools/battor_agent/battor_connection_impl.h" | 12 #include "tools/battor_agent/battor_connection_impl.h" |
| 12 #include "tools/battor_agent/battor_sample_converter.h" | 13 #include "tools/battor_agent/battor_sample_converter.h" |
| 13 | 14 |
| 14 using std::vector; | 15 using std::vector; |
| 15 | 16 |
| 16 namespace battor { | 17 namespace battor { |
| 17 | 18 |
| 18 namespace { | 19 namespace { |
| 19 | 20 |
| 20 // The number of seconds that it takes a BattOr to reset. | |
| 21 const uint8_t kBattOrResetTimeSeconds = 5; | |
| 22 | |
| 23 // The maximum number of times to retry when reading a message. | 21 // The maximum number of times to retry when reading a message. |
| 24 const uint8_t kMaxReadAttempts = 20; | 22 const uint8_t kMaxReadAttempts = 20; |
| 25 | 23 |
| 24 // The maximum number of times to retry when init'ing a battor. | |
|
charliea (OOO until 10-5)
2016/06/10 17:05:33
same nit about maybe putting this above the read a
aschulman
2016/06/10 18:27:25
Done.
| |
| 25 const uint8_t kMaxInitAttempts = 20; | |
| 26 | |
| 27 // The number of milliseconds to wait before trying to init again. | |
| 28 const uint16_t kInitRetryDelayMilliseconds = 100; | |
| 29 | |
| 26 // The number of milliseconds to wait before trying to read a message again. | 30 // The number of milliseconds to wait before trying to read a message again. |
| 27 const uint8_t kReadRetryDelayMilliseconds = 1; | 31 const uint8_t kReadRetryDelayMilliseconds = 1; |
| 28 | 32 |
| 29 // The amount of time we need to wait after recording a clock sync marker in | 33 // The amount of time we need to wait after recording a clock sync marker in |
| 30 // order to ensure that the sample we synced to doesn't get thrown out. | 34 // order to ensure that the sample we synced to doesn't get thrown out. |
| 31 const uint8_t kStopTracingClockSyncDelayMilliseconds = 100; | 35 const uint8_t kStopTracingClockSyncDelayMilliseconds = 100; |
| 32 | 36 |
| 33 // The number of seconds allowed for a given action before timing out. | 37 // The number of seconds allowed for a given action before timing out. |
| 34 const uint8_t kBattOrTimeoutSeconds = 10; | 38 const uint8_t kBattOrTimeoutSeconds = 4; |
| 35 | 39 |
| 36 // Returns true if the specified vector of bytes decodes to a message that is an | 40 // Returns true if the specified vector of bytes decodes to a message that is an |
| 37 // ack for the specified control message type. | 41 // ack for the specified control message type. |
| 38 bool IsAckOfControlCommand(BattOrMessageType message_type, | 42 bool IsAckOfControlCommand(BattOrMessageType message_type, |
| 39 BattOrControlMessageType control_message_type, | 43 BattOrControlMessageType control_message_type, |
| 40 const vector<char>& msg) { | 44 const vector<char>& msg) { |
| 41 if (message_type != BATTOR_MESSAGE_TYPE_CONTROL_ACK) | 45 if (message_type != BATTOR_MESSAGE_TYPE_CONTROL_ACK) |
| 42 return false; | 46 return false; |
| 43 | 47 |
| 44 if (msg.size() != sizeof(BattOrControlMessageAck)) | 48 if (msg.size() != sizeof(BattOrControlMessageAck)) |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 Listener* listener, | 116 Listener* listener, |
| 113 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, | 117 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, |
| 114 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) | 118 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) |
| 115 : connection_(new BattOrConnectionImpl(path, | 119 : connection_(new BattOrConnectionImpl(path, |
| 116 this, | 120 this, |
| 117 file_thread_task_runner, | 121 file_thread_task_runner, |
| 118 ui_thread_task_runner)), | 122 ui_thread_task_runner)), |
| 119 listener_(listener), | 123 listener_(listener), |
| 120 last_action_(Action::INVALID), | 124 last_action_(Action::INVALID), |
| 121 command_(Command::INVALID), | 125 command_(Command::INVALID), |
| 122 num_read_attempts_(0) { | 126 num_read_attempts_(0), |
| 127 num_init_attempts_(0) { | |
|
charliea (OOO until 10-5)
2016/06/10 17:05:33
same nit (swap init and read)
aschulman
2016/06/10 18:27:24
Done.
| |
| 123 // We don't care what thread the constructor is called on - we only care that | 128 // We don't care what thread the constructor is called on - we only care that |
| 124 // all of the other method invocations happen on the same thread. | 129 // all of the other method invocations happen on the same thread. |
| 125 thread_checker_.DetachFromThread(); | 130 thread_checker_.DetachFromThread(); |
| 126 } | 131 } |
| 127 | 132 |
| 128 BattOrAgent::~BattOrAgent() { | 133 BattOrAgent::~BattOrAgent() { |
| 129 DCHECK(thread_checker_.CalledOnValidThread()); | 134 DCHECK(thread_checker_.CalledOnValidThread()); |
| 130 } | 135 } |
| 131 | 136 |
| 132 void BattOrAgent::StartTracing() { | 137 void BattOrAgent::StartTracing() { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 165 // Return immediately if opening the connection already timed out. | 170 // Return immediately if opening the connection already timed out. |
| 166 if (timeout_callback_.IsCancelled()) | 171 if (timeout_callback_.IsCancelled()) |
| 167 return; | 172 return; |
| 168 timeout_callback_.Cancel(); | 173 timeout_callback_.Cancel(); |
| 169 | 174 |
| 170 if (!success) { | 175 if (!success) { |
| 171 CompleteCommand(BATTOR_ERROR_CONNECTION_FAILED); | 176 CompleteCommand(BATTOR_ERROR_CONNECTION_FAILED); |
| 172 return; | 177 return; |
| 173 } | 178 } |
| 174 | 179 |
| 180 | |
|
charliea (OOO until 10-5)
2016/06/10 17:05:33
nit: delete extra \n
aschulman
2016/06/10 18:27:25
Done.
| |
| 175 switch (command_) { | 181 switch (command_) { |
| 176 case Command::START_TRACING: | 182 case Command::START_TRACING: |
| 177 // TODO(charliea): Ideally, we'd just like to send an init, and the BattOr | 183 num_init_attempts_ = 1; |
| 178 // firmware can handle whether a reset is necessary or not, sending an | 184 PerformAction(Action::SEND_INIT); |
| 179 // init ack regardless. This reset can be removed once this is true. | |
| 180 // https://github.com/aschulm/battor/issues/30 tracks this. | |
| 181 PerformAction(Action::SEND_RESET); | |
| 182 return; | 185 return; |
| 183 case Command::STOP_TRACING: | 186 case Command::STOP_TRACING: |
| 184 PerformAction(Action::SEND_EEPROM_REQUEST); | 187 PerformAction(Action::SEND_EEPROM_REQUEST); |
| 185 return; | 188 return; |
| 186 case Command::RECORD_CLOCK_SYNC_MARKER: | 189 case Command::RECORD_CLOCK_SYNC_MARKER: |
| 187 PerformAction(Action::SEND_CURRENT_SAMPLE_REQUEST); | 190 PerformAction(Action::SEND_CURRENT_SAMPLE_REQUEST); |
| 188 return; | 191 return; |
| 189 case Command::INVALID: | 192 case Command::INVALID: |
| 190 NOTREACHED(); | 193 NOTREACHED(); |
| 191 } | 194 } |
| 192 } | 195 } |
| 193 | 196 |
| 194 void BattOrAgent::OnBytesSent(bool success) { | 197 void BattOrAgent::OnBytesSent(bool success) { |
| 195 DCHECK(thread_checker_.CalledOnValidThread()); | 198 DCHECK(thread_checker_.CalledOnValidThread()); |
| 196 | 199 |
| 197 // Return immediately if whatever action we were trying to perform already | 200 // Return immediately if whatever action we were trying to perform already |
| 198 // timed out. | 201 // timed out. |
| 199 if (timeout_callback_.IsCancelled()) | 202 if (timeout_callback_.IsCancelled()) |
| 200 return; | 203 return; |
| 201 timeout_callback_.Cancel(); | 204 timeout_callback_.Cancel(); |
| 202 | 205 |
| 203 if (!success) { | 206 if (!success) { |
| 204 CompleteCommand(BATTOR_ERROR_SEND_ERROR); | 207 CompleteCommand(BATTOR_ERROR_SEND_ERROR); |
| 205 return; | 208 return; |
| 206 } | 209 } |
| 207 | 210 |
| 208 switch (last_action_) { | 211 switch (last_action_) { |
| 209 case Action::SEND_RESET: | |
| 210 // TODO(charliea): Ideally, we'd just like to send an init, and the BattOr | |
| 211 // firmware can handle whether a reset is necessary or not, sending an | |
| 212 // init ack regardless. This reset can be removed once this is true. | |
| 213 // https://github.com/aschulm/battor/issues/30 tracks this. | |
| 214 | |
| 215 // Wait for the reset to happen before sending the init message. | |
| 216 PerformDelayedAction(Action::SEND_INIT, base::TimeDelta::FromSeconds( | |
| 217 kBattOrResetTimeSeconds)); | |
| 218 return; | |
| 219 case Action::SEND_INIT: | 212 case Action::SEND_INIT: |
| 220 PerformAction(Action::READ_INIT_ACK); | 213 PerformAction(Action::READ_INIT_ACK); |
| 221 return; | 214 return; |
| 222 case Action::SEND_SET_GAIN: | 215 case Action::SEND_SET_GAIN: |
| 223 PerformAction(Action::READ_SET_GAIN_ACK); | 216 PerformAction(Action::READ_SET_GAIN_ACK); |
| 224 return; | 217 return; |
| 225 case Action::SEND_START_TRACING: | 218 case Action::SEND_START_TRACING: |
| 226 PerformAction(Action::READ_START_TRACING_ACK); | 219 PerformAction(Action::READ_START_TRACING_ACK); |
| 227 return; | 220 return; |
| 228 case Action::SEND_EEPROM_REQUEST: | 221 case Action::SEND_EEPROM_REQUEST: |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 259 case Action::READ_CURRENT_SAMPLE: | 252 case Action::READ_CURRENT_SAMPLE: |
| 260 if (++num_read_attempts_ > kMaxReadAttempts) { | 253 if (++num_read_attempts_ > kMaxReadAttempts) { |
| 261 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); | 254 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); |
| 262 return; | 255 return; |
| 263 } | 256 } |
| 264 | 257 |
| 265 PerformDelayedAction(last_action_, base::TimeDelta::FromMilliseconds( | 258 PerformDelayedAction(last_action_, base::TimeDelta::FromMilliseconds( |
| 266 kReadRetryDelayMilliseconds)); | 259 kReadRetryDelayMilliseconds)); |
| 267 return; | 260 return; |
| 268 | 261 |
| 262 // Retry sending an INIT if it an ACK is not received. | |
| 263 case Action::SEND_INIT: | |
| 264 case Action::READ_INIT_ACK: | |
| 265 if (++num_init_attempts_ < kMaxInitAttempts) { | |
|
charliea (OOO until 10-5)
2016/06/10 17:05:33
This definitely stems from problematic code that I
aschulman
2016/06/10 18:27:25
Done.
| |
| 266 PerformDelayedAction(Action::SEND_INIT, | |
| 267 base::TimeDelta::FromMilliseconds(kInitRetryDelayMilliseconds)); | |
| 268 } else { | |
| 269 CompleteCommand(BATTOR_ERROR_INIT_MAX_RETRIES); | |
| 270 } | |
| 271 | |
| 272 return; | |
| 273 | |
| 269 default: | 274 default: |
| 270 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); | 275 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); |
| 271 return; | 276 return; |
| 272 } | 277 } |
| 273 } | 278 } |
| 274 | 279 |
| 275 switch (last_action_) { | 280 switch (last_action_) { |
| 276 case Action::READ_INIT_ACK: | 281 case Action::READ_INIT_ACK: |
| 277 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_INIT, | 282 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_INIT, |
| 278 *bytes)) { | 283 *bytes)) { |
| 279 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); | 284 if (++num_init_attempts_ < kMaxInitAttempts) { |
| 280 return; | 285 PerformDelayedAction(Action::SEND_INIT, |
| 286 base::TimeDelta::FromMilliseconds(kInitRetryDelayMilliseconds)); | |
| 287 } else { | |
| 288 CompleteCommand(BATTOR_ERROR_INIT_MAX_RETRIES); | |
| 289 } | |
| 290 | |
| 291 return; | |
|
charliea (OOO until 10-5)
2016/06/10 17:05:33
I think this return; is indented wrong (by one spa
aschulman
2016/06/10 18:27:24
Done.
| |
| 281 } | 292 } |
| 282 | 293 |
| 283 PerformAction(Action::SEND_SET_GAIN); | 294 PerformAction(Action::SEND_SET_GAIN); |
| 284 return; | 295 return; |
| 285 | 296 |
| 286 case Action::READ_SET_GAIN_ACK: | 297 case Action::READ_SET_GAIN_ACK: |
| 287 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, | 298 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, |
| 288 *bytes)) { | 299 *bytes)) { |
| 289 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); | 300 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); |
| 290 return; | 301 return; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 393 base::TimeDelta::FromSeconds(kBattOrTimeoutSeconds)); | 404 base::TimeDelta::FromSeconds(kBattOrTimeoutSeconds)); |
| 394 | 405 |
| 395 last_action_ = action; | 406 last_action_ = action; |
| 396 | 407 |
| 397 switch (action) { | 408 switch (action) { |
| 398 case Action::REQUEST_CONNECTION: | 409 case Action::REQUEST_CONNECTION: |
| 399 BeginConnect(); | 410 BeginConnect(); |
| 400 return; | 411 return; |
| 401 | 412 |
| 402 // The following actions are required for StartTracing: | 413 // The following actions are required for StartTracing: |
| 403 case Action::SEND_RESET: | |
| 404 // Reset the BattOr to clear any preexisting state. After sending the | |
| 405 // reset signal, we need to wait for the reset to finish before issuing | |
| 406 // further commands. | |
| 407 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0, 0); | |
| 408 return; | |
| 409 case Action::SEND_INIT: | 414 case Action::SEND_INIT: |
| 410 // After resetting the BattOr, we need to make sure to flush the serial | 415 // Clear out the serial data that may exist from prior init attempts. |
| 411 // stream. Strange data may have been written into it during the reset. | |
| 412 connection_->Flush(); | 416 connection_->Flush(); |
| 413 | 417 |
| 414 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_INIT, 0, 0); | 418 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_INIT, 0, 0); |
| 415 return; | 419 return; |
| 416 case Action::READ_INIT_ACK: | 420 case Action::READ_INIT_ACK: |
| 417 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); | 421 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); |
| 418 return; | 422 return; |
| 419 case Action::SEND_SET_GAIN: | 423 case Action::SEND_SET_GAIN: |
| 420 // Set the BattOr's gain. Setting the gain tells the BattOr the range of | 424 // Set the BattOr's gain. Setting the gain tells the BattOr the range of |
| 421 // power measurements that we expect to see. | 425 // power measurements that we expect to see. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 476 } | 480 } |
| 477 } | 481 } |
| 478 | 482 |
| 479 void BattOrAgent::PerformDelayedAction(Action action, base::TimeDelta delay) { | 483 void BattOrAgent::PerformDelayedAction(Action action, base::TimeDelta delay) { |
| 480 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 484 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 481 FROM_HERE, base::Bind(&BattOrAgent::PerformAction, AsWeakPtr(), action), | 485 FROM_HERE, base::Bind(&BattOrAgent::PerformAction, AsWeakPtr(), action), |
| 482 delay); | 486 delay); |
| 483 } | 487 } |
| 484 | 488 |
| 485 void BattOrAgent::OnActionTimeout() { | 489 void BattOrAgent::OnActionTimeout() { |
| 486 CompleteCommand(BATTOR_ERROR_TIMEOUT); | 490 switch (last_action_) { |
| 491 case Action::READ_INIT_ACK: | |
| 492 // Cancel INIT ACK read, OnReadMessage() will fail and retry SEND_INIT. | |
|
charliea (OOO until 10-5)
2016/06/10 17:05:33
I'd put this comment inside of the if clause, beca
charliea (OOO until 10-5)
2016/06/10 17:05:33
I think the function is OnMessageRead and not OnRe
aschulman
2016/06/10 18:27:24
Done.
aschulman
2016/06/10 18:27:25
Done.
| |
| 493 if (++num_init_attempts_ < kMaxInitAttempts) | |
| 494 connection_->CancelReadMessage(); | |
| 495 else | |
| 496 CompleteCommand(BATTOR_ERROR_INIT_MAX_RETRIES); | |
| 497 | |
| 498 return; | |
| 499 | |
| 500 default: | |
| 501 CompleteCommand(BATTOR_ERROR_TIMEOUT); | |
| 502 } | |
| 503 | |
| 487 timeout_callback_.Cancel(); | 504 timeout_callback_.Cancel(); |
| 488 } | 505 } |
| 489 | 506 |
| 490 void BattOrAgent::SendControlMessage(BattOrControlMessageType type, | 507 void BattOrAgent::SendControlMessage(BattOrControlMessageType type, |
| 491 uint16_t param1, | 508 uint16_t param1, |
| 492 uint16_t param2) { | 509 uint16_t param2) { |
| 493 DCHECK(thread_checker_.CalledOnValidThread()); | 510 DCHECK(thread_checker_.CalledOnValidThread()); |
| 494 | 511 |
| 495 BattOrControlMessage msg{type, param1, param2}; | 512 BattOrControlMessage msg{type, param1, param2}; |
| 496 connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, &msg, sizeof(msg)); | 513 connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, &msg, sizeof(msg)); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 561 if (clock_sync_marker != clock_sync_markers_.end()) | 578 if (clock_sync_marker != clock_sync_markers_.end()) |
| 562 trace_stream << " <" << clock_sync_marker->second << ">"; | 579 trace_stream << " <" << clock_sync_marker->second << ">"; |
| 563 | 580 |
| 564 trace_stream << std::endl; | 581 trace_stream << std::endl; |
| 565 } | 582 } |
| 566 | 583 |
| 567 return trace_stream.str(); | 584 return trace_stream.str(); |
| 568 } | 585 } |
| 569 | 586 |
| 570 } // namespace battor | 587 } // namespace battor |
| OLD | NEW |