Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(301)

Side by Side Diff: tools/battor_agent/battor_agent.cc

Issue 2343973003: Prototype of fix for mac FTDI crash where the entire trace is read even if there is an error (e.g.,…
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/battor_agent/battor_agent.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 maximum number of times to retry when init'ing a battor. 21 // The maximum number of times to retry when init'ing a battor.
21 const uint8_t kMaxInitAttempts = 20; 22 const uint8_t kMaxInitAttempts = 20;
22 23
23 // The number of milliseconds to wait before trying to init again. 24 // The number of milliseconds to wait before trying to init again.
24 const uint16_t kInitRetryDelayMilliseconds = 100; 25 const uint16_t kInitRetryDelayMilliseconds = 100;
25 26
26 // The maximum number of times to retry when reading a message.
27 const uint8_t kMaxReadAttempts = 20;
28
29 // The number of milliseconds to wait before trying to read a message again.
30 const uint8_t kReadRetryDelayMilliseconds = 1;
31
32 // The amount of time we need to wait after recording a clock sync marker in 27 // The amount of time we need to wait after recording a clock sync marker in
33 // order to ensure that the sample we synced to doesn't get thrown out. 28 // order to ensure that the sample we synced to doesn't get thrown out.
34 const uint8_t kStopTracingClockSyncDelayMilliseconds = 100; 29 const uint8_t kStopTracingClockSyncDelayMilliseconds = 100;
35 30
36 // The number of seconds allowed for a given action before timing out. 31 // The number of seconds allowed for a given action before timing out.
37 const uint8_t kBattOrTimeoutSeconds = 4; 32 const uint8_t kBattOrTimeoutSeconds = 4;
38 33
39 // Returns true if the specified vector of bytes decodes to a message that is an 34 // Returns true if the specified vector of bytes decodes to a message that is an
40 // ack for the specified control message type. 35 // ack for the specified control message type.
41 bool IsAckOfControlCommand(BattOrMessageType message_type, 36 bool IsAckOfControlCommand(BattOrMessageType message_type,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 79
85 // Each frame should contain a header and an integer number of BattOr samples. 80 // Each frame should contain a header and an integer number of BattOr samples.
86 if ((msg.size() - sizeof(BattOrFrameHeader)) % sizeof(RawBattOrSample) != 0) 81 if ((msg.size() - sizeof(BattOrFrameHeader)) % sizeof(RawBattOrSample) != 0)
87 return false; 82 return false;
88 83
89 // The first bytes in the frame contain the frame header. 84 // The first bytes in the frame contain the frame header.
90 const char* frame_ptr = reinterpret_cast<const char*>(msg.data()); 85 const char* frame_ptr = reinterpret_cast<const char*>(msg.data());
91 memcpy(frame_header, frame_ptr, sizeof(BattOrFrameHeader)); 86 memcpy(frame_header, frame_ptr, sizeof(BattOrFrameHeader));
92 frame_ptr += sizeof(BattOrFrameHeader); 87 frame_ptr += sizeof(BattOrFrameHeader);
93 88
94 if (frame_header->sequence_number != expected_sequence_number) { 89 if (frame_header->sequence_number != expected_sequence_number)
95 LOG(WARNING) << "Unexpected sequence number: wanted "
96 << expected_sequence_number << ", but got "
97 << frame_header->sequence_number << ".";
98 return false; 90 return false;
99 }
100 91
101 size_t remaining_bytes = msg.size() - sizeof(BattOrFrameHeader); 92 size_t remaining_bytes = msg.size() - sizeof(BattOrFrameHeader);
102 if (remaining_bytes != frame_header->length) 93 if (remaining_bytes != frame_header->length)
103 return false; 94 return false;
104 95
105 samples->resize(remaining_bytes / sizeof(RawBattOrSample)); 96 samples->resize(remaining_bytes / sizeof(RawBattOrSample));
106 memcpy(samples->data(), frame_ptr, remaining_bytes); 97 memcpy(samples->data(), frame_ptr, remaining_bytes);
107 98
108 return true; 99 return true;
109 } 100 }
110 101
111 } // namespace 102 } // namespace
112 103
113 BattOrAgent::BattOrAgent( 104 BattOrAgent::BattOrAgent(
114 const std::string& path, 105 const std::string& path,
115 Listener* listener, 106 Listener* listener,
116 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, 107 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner,
117 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) 108 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner)
118 : connection_(new BattOrConnectionImpl(path, 109 : connection_(new BattOrConnectionImpl(path,
119 this, 110 this,
120 file_thread_task_runner, 111 file_thread_task_runner,
121 ui_thread_task_runner)), 112 ui_thread_task_runner)),
122 listener_(listener), 113 listener_(listener),
123 last_action_(Action::INVALID), 114 last_action_(Action::INVALID),
124 command_(Command::INVALID), 115 command_(Command::INVALID),
125 num_init_attempts_(0), 116 num_init_attempts_(0) {
126 num_read_attempts_(0) {
127 // We don't care what thread the constructor is called on - we only care that 117 // We don't care what thread the constructor is called on - we only care that
128 // all of the other method invocations happen on the same thread. 118 // all of the other method invocations happen on the same thread.
129 thread_checker_.DetachFromThread(); 119 thread_checker_.DetachFromThread();
130 } 120 }
131 121
132 BattOrAgent::~BattOrAgent() { 122 BattOrAgent::~BattOrAgent() {
133 DCHECK(thread_checker_.CalledOnValidThread()); 123 DCHECK(thread_checker_.CalledOnValidThread());
134 } 124 }
135 125
136 void BattOrAgent::StartTracing() { 126 void BattOrAgent::StartTracing() {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 case Action::SEND_INIT: 200 case Action::SEND_INIT:
211 PerformAction(Action::READ_INIT_ACK); 201 PerformAction(Action::READ_INIT_ACK);
212 return; 202 return;
213 case Action::SEND_SET_GAIN: 203 case Action::SEND_SET_GAIN:
214 PerformAction(Action::READ_SET_GAIN_ACK); 204 PerformAction(Action::READ_SET_GAIN_ACK);
215 return; 205 return;
216 case Action::SEND_START_TRACING: 206 case Action::SEND_START_TRACING:
217 PerformAction(Action::READ_START_TRACING_ACK); 207 PerformAction(Action::READ_START_TRACING_ACK);
218 return; 208 return;
219 case Action::SEND_EEPROM_REQUEST: 209 case Action::SEND_EEPROM_REQUEST:
220 num_read_attempts_ = 1;
221 PerformAction(Action::READ_EEPROM); 210 PerformAction(Action::READ_EEPROM);
222 return; 211 return;
223 case Action::SEND_SAMPLES_REQUEST: 212 case Action::SEND_SAMPLES_REQUEST:
224 num_read_attempts_ = 1;
225 PerformAction(Action::READ_CALIBRATION_FRAME); 213 PerformAction(Action::READ_CALIBRATION_FRAME);
226 return; 214 return;
227 case Action::SEND_CURRENT_SAMPLE_REQUEST: 215 case Action::SEND_CURRENT_SAMPLE_REQUEST:
228 num_read_attempts_ = 1;
229 PerformAction(Action::READ_CURRENT_SAMPLE); 216 PerformAction(Action::READ_CURRENT_SAMPLE);
230 return; 217 return;
231 default: 218 default:
232 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 219 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE);
233 } 220 }
234 } 221 }
235 222
236 void BattOrAgent::OnMessageRead(bool success, 223 void BattOrAgent::OnMessageRead(bool success,
237 BattOrMessageType type, 224 BattOrMessageType type,
238 std::unique_ptr<vector<char>> bytes) { 225 std::unique_ptr<vector<char>> bytes) {
239 // Return immediately if whatever action we were trying to perform already 226 // Return immediately if whatever action we were trying to perform already
240 // timed out. 227 // timed out.
241 if (timeout_callback_.IsCancelled()) 228 if (timeout_callback_.IsCancelled())
242 return; 229 return;
243 timeout_callback_.Cancel(); 230 timeout_callback_.Cancel();
244 231
245 if (!success) { 232 if (!success) {
246 switch (last_action_) { 233 switch (last_action_) {
247 case Action::READ_EEPROM: 234 case Action::READ_EEPROM:
235 case Action::READ_CURRENT_SAMPLE:
236 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR);
237 return;
248 case Action::READ_CALIBRATION_FRAME: 238 case Action::READ_CALIBRATION_FRAME:
249 case Action::READ_DATA_FRAME: 239 case Action::READ_DATA_FRAME:
250 case Action::READ_CURRENT_SAMPLE: 240 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR);
251 if (num_read_attempts_++ > kMaxReadAttempts) {
252 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR);
253 return;
254 }
255
256 PerformDelayedAction(last_action_, base::TimeDelta::FromMilliseconds(
257 kReadRetryDelayMilliseconds));
258 return; 241 return;
259
260 // Retry sending an INIT if it an ACK is not received. 242 // Retry sending an INIT if it an ACK is not received.
261 case Action::SEND_INIT: 243 case Action::SEND_INIT:
262 case Action::READ_INIT_ACK: 244 case Action::READ_INIT_ACK:
263 if (num_init_attempts_++ < kMaxInitAttempts) { 245 if (num_init_attempts_++ < kMaxInitAttempts) {
264 PerformDelayedAction(Action::SEND_INIT, 246 PerformDelayedAction(Action::SEND_INIT,
265 base::TimeDelta::FromMilliseconds(kInitRetryDelayMilliseconds)); 247 base::TimeDelta::FromMilliseconds(kInitRetryDelayMilliseconds));
266 } else { 248 } else {
267 CompleteCommand(BATTOR_ERROR_TOO_MANY_INIT_RETRIES); 249 CompleteCommand(BATTOR_ERROR_TOO_MANY_INIT_RETRIES);
268 } 250 }
269 251
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 base::TimeDelta request_samples_delay = std::max( 310 base::TimeDelta request_samples_delay = std::max(
329 min_request_samples_time - base::TimeTicks::Now(), base::TimeDelta()); 311 min_request_samples_time - base::TimeTicks::Now(), base::TimeDelta());
330 312
331 PerformDelayedAction(Action::SEND_SAMPLES_REQUEST, request_samples_delay); 313 PerformDelayedAction(Action::SEND_SAMPLES_REQUEST, request_samples_delay);
332 return; 314 return;
333 } 315 }
334 case Action::READ_CALIBRATION_FRAME: { 316 case Action::READ_CALIBRATION_FRAME: {
335 BattOrFrameHeader frame_header; 317 BattOrFrameHeader frame_header;
336 if (!ParseSampleFrame(type, *bytes, next_sequence_number_++, 318 if (!ParseSampleFrame(type, *bytes, next_sequence_number_++,
337 &frame_header, &calibration_frame_)) { 319 &frame_header, &calibration_frame_)) {
338 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 320 if (read_frame_error_ == BATTOR_ERROR_NONE)
339 return; 321 read_frame_error_ = BATTOR_ERROR_UNEXPECTED_MESSAGE;
322 } else {
323 // Make sure that the calibration frame has actual samples in it.
324 if (calibration_frame_.empty()) {
325 if (read_frame_error_ == BATTOR_ERROR_NONE)
326 read_frame_error_ = BATTOR_ERROR_UNEXPECTED_MESSAGE;
327 }
340 } 328 }
341 329
342 // Make sure that the calibration frame has actual samples in it.
343 if (calibration_frame_.empty()) {
344 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE);
345 return;
346 }
347
348 num_read_attempts_ = 1;
349 PerformAction(Action::READ_DATA_FRAME); 330 PerformAction(Action::READ_DATA_FRAME);
350 return; 331 return;
351 } 332 }
352 333
353 case Action::READ_DATA_FRAME: { 334 case Action::READ_DATA_FRAME: {
354 BattOrFrameHeader frame_header; 335 BattOrFrameHeader frame_header;
355 vector<RawBattOrSample> frame; 336 vector<RawBattOrSample> frame;
356 if (!ParseSampleFrame(type, *bytes, next_sequence_number_++, 337 if (!ParseSampleFrame(type, *bytes, next_sequence_number_++,
357 &frame_header, &frame)) { 338 &frame_header, &frame)) {
358 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 339 if (read_frame_error_ == BATTOR_ERROR_NONE)
359 return; 340 read_frame_error_ = BATTOR_ERROR_UNEXPECTED_MESSAGE;
341 } else {
342 // Check for the empty frame the BattOr uses to indicate it's done
343 // streaming samples.
344 if (frame.empty()) {
345 CompleteCommand(BATTOR_ERROR_NONE);
346 return;
347 }
348
349 samples_.insert(samples_.end(), frame.begin(), frame.end());
360 } 350 }
361 351
362 // Check for the empty frame the BattOr uses to indicate it's done
363 // streaming samples.
364 if (frame.empty()) {
365 CompleteCommand(BATTOR_ERROR_NONE);
366 return;
367 }
368
369 samples_.insert(samples_.end(), frame.begin(), frame.end());
370
371 num_read_attempts_ = 1;
372 PerformAction(Action::READ_DATA_FRAME); 352 PerformAction(Action::READ_DATA_FRAME);
373 return; 353 return;
374 } 354 }
375 355
376 case Action::READ_CURRENT_SAMPLE: 356 case Action::READ_CURRENT_SAMPLE:
377 if (type != BATTOR_MESSAGE_TYPE_CONTROL_ACK || 357 if (type != BATTOR_MESSAGE_TYPE_CONTROL_ACK ||
378 bytes->size() != sizeof(uint32_t)) { 358 bytes->size() != sizeof(uint32_t)) {
379 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 359 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE);
380 return; 360 return;
381 } 361 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 case Action::SEND_SAMPLES_REQUEST: 427 case Action::SEND_SAMPLES_REQUEST:
448 // Send a request to the BattOr to tell it to start streaming the samples 428 // Send a request to the BattOr to tell it to start streaming the samples
449 // that it's stored on its SD card over the serial connection. 429 // that it's stored on its SD card over the serial connection.
450 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_READ_SD_UART, 0, 0); 430 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_READ_SD_UART, 0, 0);
451 return; 431 return;
452 case Action::READ_CALIBRATION_FRAME: 432 case Action::READ_CALIBRATION_FRAME:
453 // Data frames are numbered starting at zero and counting up by one each 433 // Data frames are numbered starting at zero and counting up by one each
454 // data frame. We keep track of the next frame sequence number we expect 434 // data frame. We keep track of the next frame sequence number we expect
455 // to see to ensure we don't miss any data. 435 // to see to ensure we don't miss any data.
456 next_sequence_number_ = 0; 436 next_sequence_number_ = 0;
437
438 // Initialize error that could be encountered while reading data.
439 read_frame_error_ = BATTOR_ERROR_NONE;
457 case Action::READ_DATA_FRAME: 440 case Action::READ_DATA_FRAME:
458 // The first frame sent back from the BattOr contains voltage and current 441 // The first frame sent back from the BattOr contains voltage and current
459 // data that excludes whatever device is being measured from the 442 // data that excludes whatever device is being measured from the
460 // circuit. We use this first frame to establish a baseline voltage and 443 // circuit. We use this first frame to establish a baseline voltage and
461 // current. 444 // current.
462 // 445 //
463 // All further frames contain real (but uncalibrated) voltage and current 446 // All further frames contain real (but uncalibrated) voltage and current
464 // data. 447 // data.
465 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_SAMPLES); 448 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_SAMPLES);
466 return; 449 return;
(...skipping 19 matching lines...) Expand all
486 469
487 void BattOrAgent::OnActionTimeout() { 470 void BattOrAgent::OnActionTimeout() {
488 switch (last_action_) { 471 switch (last_action_) {
489 case Action::READ_INIT_ACK: 472 case Action::READ_INIT_ACK:
490 if (num_init_attempts_++ < kMaxInitAttempts) { 473 if (num_init_attempts_++ < kMaxInitAttempts) {
491 // OnMessageRead() will fail and retry SEND_INIT. 474 // OnMessageRead() will fail and retry SEND_INIT.
492 connection_->CancelReadMessage(); 475 connection_->CancelReadMessage();
493 } else { 476 } else {
494 CompleteCommand(BATTOR_ERROR_TOO_MANY_INIT_RETRIES); 477 CompleteCommand(BATTOR_ERROR_TOO_MANY_INIT_RETRIES);
495 } 478 }
496 479 return;
480 case Action::READ_CALIBRATION_FRAME:
481 case Action::READ_DATA_FRAME:
482 // Fail with the first frame read error error if one was encountered.
483 if (read_frame_error_ != BATTOR_ERROR_NONE)
484 CompleteCommand(read_frame_error_);
485 else
486 CompleteCommand(BATTOR_ERROR_TIMEOUT);
497 return; 487 return;
498 488
499 default: 489 default:
500 CompleteCommand(BATTOR_ERROR_TIMEOUT); 490 CompleteCommand(BATTOR_ERROR_TIMEOUT);
501 } 491 }
502 492
503 timeout_callback_.Cancel(); 493 timeout_callback_.Cancel();
504 } 494 }
505 495
506 void BattOrAgent::SendControlMessage(BattOrControlMessageType type, 496 void BattOrAgent::SendControlMessage(BattOrControlMessageType type,
507 uint16_t param1, 497 uint16_t param1,
508 uint16_t param2) { 498 uint16_t param2) {
509 DCHECK(thread_checker_.CalledOnValidThread()); 499 DCHECK(thread_checker_.CalledOnValidThread());
510 500
511 BattOrControlMessage msg{type, param1, param2}; 501 BattOrControlMessage msg{type, param1, param2};
512 connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, &msg, sizeof(msg)); 502 connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, &msg, sizeof(msg));
513 } 503 }
514 504
515 void BattOrAgent::CompleteCommand(BattOrError error) { 505 void BattOrAgent::CompleteCommand(BattOrError error) {
516 switch (command_) { 506 switch (command_) {
517 case Command::START_TRACING: 507 case Command::START_TRACING:
518 base::ThreadTaskRunnerHandle::Get()->PostTask( 508 base::ThreadTaskRunnerHandle::Get()->PostTask(
519 FROM_HERE, base::Bind(&Listener::OnStartTracingComplete, 509 FROM_HERE, base::Bind(&Listener::OnStartTracingComplete,
520 base::Unretained(listener_), error)); 510 base::Unretained(listener_), error));
521 break; 511 break;
522 case Command::STOP_TRACING: 512 case Command::STOP_TRACING:
513 if (read_frame_error_ != BATTOR_ERROR_NONE)
514 error = read_frame_error_;
515
523 base::ThreadTaskRunnerHandle::Get()->PostTask( 516 base::ThreadTaskRunnerHandle::Get()->PostTask(
524 FROM_HERE, 517 FROM_HERE,
525 base::Bind(&Listener::OnStopTracingComplete, 518 base::Bind(&Listener::OnStopTracingComplete,
526 base::Unretained(listener_), SamplesToString(), error)); 519 base::Unretained(listener_), SamplesToString(), error));
527 break; 520 break;
528 case Command::RECORD_CLOCK_SYNC_MARKER: 521 case Command::RECORD_CLOCK_SYNC_MARKER:
529 base::ThreadTaskRunnerHandle::Get()->PostTask( 522 base::ThreadTaskRunnerHandle::Get()->PostTask(
530 FROM_HERE, base::Bind(&Listener::OnRecordClockSyncMarkerComplete, 523 FROM_HERE, base::Bind(&Listener::OnRecordClockSyncMarkerComplete,
531 base::Unretained(listener_), error)); 524 base::Unretained(listener_), error));
532 break; 525 break;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 if (clock_sync_marker != clock_sync_markers_.end()) 570 if (clock_sync_marker != clock_sync_markers_.end())
578 trace_stream << " <" << clock_sync_marker->second << ">"; 571 trace_stream << " <" << clock_sync_marker->second << ">";
579 572
580 trace_stream << std::endl; 573 trace_stream << std::endl;
581 } 574 }
582 575
583 return trace_stream.str(); 576 return trace_stream.str();
584 } 577 }
585 578
586 } // namespace battor 579 } // namespace battor
OLDNEW
« no previous file with comments | « tools/battor_agent/battor_agent.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698