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 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/threading/thread_task_runner_handle.h" | 10 #include "base/threading/thread_task_runner_handle.h" |
| 11 #include "tools/battor_agent/battor_connection_impl.h" | 11 #include "tools/battor_agent/battor_connection_impl.h" |
| 12 #include "tools/battor_agent/battor_sample_converter.h" | 12 #include "tools/battor_agent/battor_sample_converter.h" |
| 13 | 13 |
| 14 using std::vector; | 14 using std::vector; |
| 15 | 15 |
| 16 namespace battor { | 16 namespace battor { |
| 17 | 17 |
| 18 namespace { | 18 namespace { |
| 19 | 19 |
| 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. | 20 // The maximum number of times to retry when reading a message. |
| 24 const uint8_t kMaxReadAttempts = 20; | 21 const uint8_t kMaxReadAttempts = 20; |
| 25 | 22 |
| 23 // The maximum number of times to retry when init'ing a battor. | |
| 24 const uint8_t kMaxInitAttempts = 20; | |
| 25 | |
| 26 // The number of milliseconds to wait before trying to init again. | |
| 27 const uint8_t kInitRetryDelayMilliseconds = 100; | |
| 28 | |
| 26 // The number of milliseconds to wait before trying to read a message again. | 29 // The number of milliseconds to wait before trying to read a message again. |
| 27 const uint8_t kReadRetryDelayMilliseconds = 1; | 30 const uint8_t kReadRetryDelayMilliseconds = 1; |
| 28 | 31 |
| 29 // The amount of time we need to wait after recording a clock sync marker in | 32 // 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. | 33 // order to ensure that the sample we synced to doesn't get thrown out. |
| 31 const uint8_t kStopTracingClockSyncDelayMilliseconds = 100; | 34 const uint8_t kStopTracingClockSyncDelayMilliseconds = 100; |
| 32 | 35 |
| 33 // The number of seconds allowed for a given action before timing out. | 36 // The number of seconds allowed for a given action before timing out. |
| 34 const uint8_t kBattOrTimeoutSeconds = 10; | 37 const uint8_t kBattOrTimeoutSeconds = 10; |
| 35 | 38 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 Listener* listener, | 115 Listener* listener, |
| 113 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, | 116 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, |
| 114 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) | 117 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) |
| 115 : connection_(new BattOrConnectionImpl(path, | 118 : connection_(new BattOrConnectionImpl(path, |
| 116 this, | 119 this, |
| 117 file_thread_task_runner, | 120 file_thread_task_runner, |
| 118 ui_thread_task_runner)), | 121 ui_thread_task_runner)), |
| 119 listener_(listener), | 122 listener_(listener), |
| 120 last_action_(Action::INVALID), | 123 last_action_(Action::INVALID), |
| 121 command_(Command::INVALID), | 124 command_(Command::INVALID), |
| 122 num_read_attempts_(0) { | 125 num_read_attempts_(0), |
| 126 num_init_attempts_(0) { | |
| 123 // We don't care what thread the constructor is called on - we only care that | 127 // 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. | 128 // all of the other method invocations happen on the same thread. |
| 125 thread_checker_.DetachFromThread(); | 129 thread_checker_.DetachFromThread(); |
| 126 } | 130 } |
| 127 | 131 |
| 128 BattOrAgent::~BattOrAgent() { | 132 BattOrAgent::~BattOrAgent() { |
| 129 DCHECK(thread_checker_.CalledOnValidThread()); | 133 DCHECK(thread_checker_.CalledOnValidThread()); |
| 130 } | 134 } |
| 131 | 135 |
| 132 void BattOrAgent::StartTracing() { | 136 void BattOrAgent::StartTracing() { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 167 return; | 171 return; |
| 168 timeout_callback_.Cancel(); | 172 timeout_callback_.Cancel(); |
| 169 | 173 |
| 170 if (!success) { | 174 if (!success) { |
| 171 CompleteCommand(BATTOR_ERROR_CONNECTION_FAILED); | 175 CompleteCommand(BATTOR_ERROR_CONNECTION_FAILED); |
| 172 return; | 176 return; |
| 173 } | 177 } |
| 174 | 178 |
| 175 switch (command_) { | 179 switch (command_) { |
| 176 case Command::START_TRACING: | 180 case Command::START_TRACING: |
| 177 // TODO(charliea): Ideally, we'd just like to send an init, and the BattOr | 181 num_init_attempts_ = 1; |
| 178 // firmware can handle whether a reset is necessary or not, sending an | 182 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; | 183 return; |
| 183 case Command::STOP_TRACING: | 184 case Command::STOP_TRACING: |
| 184 PerformAction(Action::SEND_EEPROM_REQUEST); | 185 PerformAction(Action::SEND_EEPROM_REQUEST); |
| 185 return; | 186 return; |
| 186 case Command::RECORD_CLOCK_SYNC_MARKER: | 187 case Command::RECORD_CLOCK_SYNC_MARKER: |
| 187 PerformAction(Action::SEND_CURRENT_SAMPLE_REQUEST); | 188 PerformAction(Action::SEND_CURRENT_SAMPLE_REQUEST); |
| 188 return; | 189 return; |
| 189 case Command::INVALID: | 190 case Command::INVALID: |
| 190 NOTREACHED(); | 191 NOTREACHED(); |
| 191 } | 192 } |
| 192 } | 193 } |
| 193 | 194 |
| 194 void BattOrAgent::OnBytesSent(bool success) { | 195 void BattOrAgent::OnBytesSent(bool success) { |
| 195 DCHECK(thread_checker_.CalledOnValidThread()); | 196 DCHECK(thread_checker_.CalledOnValidThread()); |
| 196 | 197 |
| 197 // Return immediately if whatever action we were trying to perform already | 198 // Return immediately if whatever action we were trying to perform already |
| 198 // timed out. | 199 // timed out. |
| 199 if (timeout_callback_.IsCancelled()) | 200 if (timeout_callback_.IsCancelled()) |
| 200 return; | 201 return; |
| 201 timeout_callback_.Cancel(); | 202 timeout_callback_.Cancel(); |
| 202 | 203 |
| 203 if (!success) { | 204 if (!success) { |
| 204 CompleteCommand(BATTOR_ERROR_SEND_ERROR); | 205 CompleteCommand(BATTOR_ERROR_SEND_ERROR); |
| 205 return; | 206 return; |
| 206 } | 207 } |
| 207 | 208 |
| 208 switch (last_action_) { | 209 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: | 210 case Action::SEND_INIT: |
| 220 PerformAction(Action::READ_INIT_ACK); | 211 PerformAction(Action::READ_INIT_ACK); |
| 221 return; | 212 return; |
| 222 case Action::SEND_SET_GAIN: | 213 case Action::SEND_SET_GAIN: |
| 223 PerformAction(Action::READ_SET_GAIN_ACK); | 214 PerformAction(Action::READ_SET_GAIN_ACK); |
| 224 return; | 215 return; |
| 225 case Action::SEND_START_TRACING: | 216 case Action::SEND_START_TRACING: |
| 226 PerformAction(Action::READ_START_TRACING_ACK); | 217 PerformAction(Action::READ_START_TRACING_ACK); |
| 227 return; | 218 return; |
| 228 case Action::SEND_EEPROM_REQUEST: | 219 case Action::SEND_EEPROM_REQUEST: |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 259 case Action::READ_CURRENT_SAMPLE: | 250 case Action::READ_CURRENT_SAMPLE: |
| 260 if (++num_read_attempts_ > kMaxReadAttempts) { | 251 if (++num_read_attempts_ > kMaxReadAttempts) { |
| 261 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); | 252 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); |
| 262 return; | 253 return; |
| 263 } | 254 } |
| 264 | 255 |
| 265 PerformDelayedAction(last_action_, base::TimeDelta::FromMilliseconds( | 256 PerformDelayedAction(last_action_, base::TimeDelta::FromMilliseconds( |
| 266 kReadRetryDelayMilliseconds)); | 257 kReadRetryDelayMilliseconds)); |
| 267 return; | 258 return; |
| 268 | 259 |
| 260 // Reset the timeout because there is a failed read after it is canceled. | |
| 261 case Action::SEND_INIT: | |
|
charliea (OOO until 10-5)
2016/05/23 14:08:52
I'm not sure I understand why this part is necessa
aschulman
2016/06/10 07:22:59
You are right this is confusing, especially since
| |
| 262 timeout_callback_.Reset( | |
| 263 base::Bind(&BattOrAgent::OnActionTimeout, AsWeakPtr())); | |
| 264 return; | |
| 265 | |
| 266 // Retry sending an INIT if it an ACK is not received. | |
| 267 case Action::READ_INIT_ACK: | |
| 268 if (++num_init_attempts_ < kMaxInitAttempts) | |
|
charliea (OOO until 10-5)
2016/05/23 14:08:51
nit: any time that there are multiple lines inside
aschulman
2016/06/10 07:22:59
Done.
| |
| 269 PerformDelayedAction(Action::SEND_INIT, | |
| 270 base::TimeDelta::FromMilliseconds(kInitRetryDelayMilliseconds)); | |
| 271 else | |
| 272 CompleteCommand(BATTOR_ERROR_INIT_ERROR); | |
| 273 return; | |
| 274 | |
| 269 default: | 275 default: |
| 270 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); | 276 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); |
| 271 return; | 277 return; |
| 272 } | 278 } |
| 273 } | 279 } |
| 274 | 280 |
| 275 switch (last_action_) { | 281 switch (last_action_) { |
| 276 case Action::READ_INIT_ACK: | 282 case Action::READ_INIT_ACK: |
| 277 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_INIT, | 283 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_INIT, |
| 278 *bytes)) { | 284 *bytes)) { |
| 279 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); | 285 if (++num_init_attempts_ < kMaxInitAttempts) |
| 286 PerformDelayedAction(Action::SEND_INIT, | |
|
charliea (OOO until 10-5)
2016/05/23 14:08:51
(same not about braces as above)
aschulman
2016/06/10 07:22:59
Done.
| |
| 287 base::TimeDelta::FromMilliseconds(kInitRetryDelayMilliseconds)); | |
| 288 else | |
| 289 CompleteCommand(BATTOR_ERROR_INIT_ERROR); | |
| 280 return; | 290 return; |
| 281 } | 291 } |
| 282 | 292 |
| 283 PerformAction(Action::SEND_SET_GAIN); | 293 PerformAction(Action::SEND_SET_GAIN); |
| 284 return; | 294 return; |
| 285 | 295 |
| 286 case Action::READ_SET_GAIN_ACK: | 296 case Action::READ_SET_GAIN_ACK: |
| 287 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, | 297 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, |
| 288 *bytes)) { | 298 *bytes)) { |
| 289 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); | 299 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 393 base::TimeDelta::FromSeconds(kBattOrTimeoutSeconds)); | 403 base::TimeDelta::FromSeconds(kBattOrTimeoutSeconds)); |
| 394 | 404 |
| 395 last_action_ = action; | 405 last_action_ = action; |
| 396 | 406 |
| 397 switch (action) { | 407 switch (action) { |
| 398 case Action::REQUEST_CONNECTION: | 408 case Action::REQUEST_CONNECTION: |
| 399 BeginConnect(); | 409 BeginConnect(); |
| 400 return; | 410 return; |
| 401 | 411 |
| 402 // The following actions are required for StartTracing: | 412 // The following actions are required for StartTracing: |
| 403 case Action::SEND_RESET: | 413 case Action::SEND_RESET: |
|
charliea (OOO until 10-5)
2016/05/23 14:08:51
This can be deleted
aschulman
2016/06/10 07:22:59
Done.
| |
| 404 // Reset the BattOr to clear any preexisting state. After sending the | 414 // 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 | 415 // reset signal, we need to wait for the reset to finish before issuing |
| 406 // further commands. | 416 // further commands. |
| 407 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0, 0); | 417 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0, 0); |
| 408 return; | 418 return; |
| 409 case Action::SEND_INIT: | 419 case Action::SEND_INIT: |
| 410 // After resetting the BattOr, we need to make sure to flush the serial | 420 // After resetting the BattOr, we need to make sure to flush the serial |
| 411 // stream. Strange data may have been written into it during the reset. | 421 // stream. Strange data may have been written into it during the reset. |
| 412 connection_->Flush(); | 422 connection_->Flush(); |
| 413 | 423 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 476 } | 486 } |
| 477 } | 487 } |
| 478 | 488 |
| 479 void BattOrAgent::PerformDelayedAction(Action action, base::TimeDelta delay) { | 489 void BattOrAgent::PerformDelayedAction(Action action, base::TimeDelta delay) { |
| 480 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 490 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 481 FROM_HERE, base::Bind(&BattOrAgent::PerformAction, AsWeakPtr(), action), | 491 FROM_HERE, base::Bind(&BattOrAgent::PerformAction, AsWeakPtr(), action), |
| 482 delay); | 492 delay); |
| 483 } | 493 } |
| 484 | 494 |
| 485 void BattOrAgent::OnActionTimeout() { | 495 void BattOrAgent::OnActionTimeout() { |
| 486 CompleteCommand(BATTOR_ERROR_TIMEOUT); | 496 switch (last_action_) { |
|
charliea (OOO until 10-5)
2016/05/23 14:08:51
nit: when it makes sense, Chromium prefers to "ear
aschulman
2016/06/10 07:22:59
Done.
| |
| 487 timeout_callback_.Cancel(); | 497 case Action::READ_INIT_ACK: |
| 498 if (++num_init_attempts_ < kMaxInitAttempts) | |
| 499 { | |
| 500 connection_->CancelReadMessage(); | |
| 501 PerformAction(Action::SEND_INIT); | |
| 502 } | |
| 503 else | |
| 504 CompleteCommand(BATTOR_ERROR_INIT_ERROR); | |
| 505 return; | |
| 506 | |
| 507 default: | |
| 508 CompleteCommand(BATTOR_ERROR_TIMEOUT); | |
| 509 timeout_callback_.Cancel(); | |
| 510 } | |
| 488 } | 511 } |
| 489 | 512 |
| 490 void BattOrAgent::SendControlMessage(BattOrControlMessageType type, | 513 void BattOrAgent::SendControlMessage(BattOrControlMessageType type, |
| 491 uint16_t param1, | 514 uint16_t param1, |
| 492 uint16_t param2) { | 515 uint16_t param2) { |
| 493 DCHECK(thread_checker_.CalledOnValidThread()); | 516 DCHECK(thread_checker_.CalledOnValidThread()); |
| 494 | 517 |
| 495 BattOrControlMessage msg{type, param1, param2}; | 518 BattOrControlMessage msg{type, param1, param2}; |
| 496 connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, &msg, sizeof(msg)); | 519 connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, &msg, sizeof(msg)); |
| 497 } | 520 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 561 if (clock_sync_marker != clock_sync_markers_.end()) | 584 if (clock_sync_marker != clock_sync_markers_.end()) |
| 562 trace_stream << " <" << clock_sync_marker->second << ">"; | 585 trace_stream << " <" << clock_sync_marker->second << ">"; |
| 563 | 586 |
| 564 trace_stream << std::endl; | 587 trace_stream << std::endl; |
| 565 } | 588 } |
| 566 | 589 |
| 567 return trace_stream.str(); | 590 return trace_stream.str(); |
| 568 } | 591 } |
| 569 | 592 |
| 570 } // namespace battor | 593 } // namespace battor |
| OLD | NEW |