Coverage Report

Created: 2025-11-09 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wpantund/src/ncp-spinel/SpinelNCPTaskPeek.cpp
Line
Count
Source
1
/*
2
 *
3
 * Copyright (c) 2017 Nest Labs, Inc.
4
 * All rights reserved.
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 *
18
 */
19
20
#if HAVE_CONFIG_H
21
#include <config.h>
22
#endif
23
24
#include "assert-macros.h"
25
#include <syslog.h>
26
#include <errno.h>
27
#include "SpinelNCPTaskPeek.h"
28
#include "SpinelNCPInstance.h"
29
#include "spinel-extra.h"
30
31
using namespace nl;
32
using namespace nl::wpantund;
33
34
nl::wpantund::SpinelNCPTaskPeek::SpinelNCPTaskPeek(
35
  SpinelNCPInstance* instance,
36
  CallbackWithStatusArg1 cb,
37
  uint32_t address,
38
  uint16_t count
39
0
):  SpinelNCPTask(instance, cb), mAddress(address), mCount(count)
40
0
{
41
0
}
42
43
int
44
nl::wpantund::SpinelNCPTaskPeek::vprocess_event(int event, va_list args)
45
0
{
46
0
  int ret = kWPANTUNDStatus_Failure;
47
48
0
  EH_BEGIN();
49
50
0
  if (!mInstance->mEnabled) {
51
0
    ret = kWPANTUNDStatus_InvalidWhenDisabled;
52
0
    finish(ret);
53
0
    EH_EXIT();
54
0
  }
55
56
0
  if (mInstance->get_ncp_state() == UPGRADING) {
57
0
    ret = kWPANTUNDStatus_InvalidForCurrentState;
58
0
    finish(ret);
59
0
    EH_EXIT();
60
0
  }
61
62
  // Wait for a bit to see if the NCP will enter the right state.
63
0
  EH_REQUIRE_WITHIN(
64
0
    NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
65
0
    !ncp_state_is_initializing(mInstance->get_ncp_state()) && !mInstance->is_initializing_ncp(),
66
0
    on_error
67
0
  );
68
69
  // The first event to a task is EVENT_STARTING_TASK. The following
70
  // line makes sure that we don't start processing this task
71
  // until it is properly scheduled. All tasks immediately receive
72
  // the initial `EVENT_STARTING_TASK` event, but further events
73
  // will only be received by that task once it is that task's turn
74
  // to execute.
75
0
  EH_WAIT_UNTIL(EVENT_STARTING_TASK != event);
76
77
0
  mNextCommand = SpinelPackData(
78
0
      SPINEL_FRAME_PACK_CMD(
79
0
          SPINEL_DATATYPE_UINT32_S   // Address
80
0
          SPINEL_DATATYPE_UINT16_S   // Count
81
0
      ),
82
0
      SPINEL_CMD_PEEK,
83
0
      mAddress,
84
0
      mCount
85
0
  );
86
87
0
  EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
88
89
0
  ret = mNextCommandRet;
90
91
0
  require_noerr(ret, on_error);
92
93
0
  if (event == EVENT_NCP(SPINEL_CMD_PEEK_RET))
94
0
  {
95
0
    spinel_prop_key_t prop_key = va_arg_small(args, spinel_prop_key_t);
96
0
    const uint8_t *frame_ptr = va_arg(args, const uint8_t*);
97
0
    spinel_size_t frame_len = va_arg_small(args, spinel_size_t);
98
0
    const uint8_t *data_ptr = NULL;
99
0
    spinel_size_t data_len = 0;
100
0
    spinel_ssize_t parsed_len;
101
0
    uint32_t address;
102
0
    uint16_t count;
103
104
0
    parsed_len = spinel_datatype_unpack(frame_ptr, frame_len, "CiLSD", NULL, NULL, &address, &count, &data_ptr, &data_len);
105
106
0
    require(parsed_len > 0, on_error);
107
0
    require(address == mAddress, on_error);
108
0
    require(data_len == mCount, on_error);
109
110
0
    ret = kWPANTUNDStatus_Ok;
111
112
0
    finish(ret, Data(data_ptr, data_len));
113
114
0
    EH_EXIT();
115
0
  }
116
117
0
on_error:
118
119
0
  if (ret == kWPANTUNDStatus_Ok) {
120
0
    ret = kWPANTUNDStatus_Failure;
121
0
  }
122
123
0
  syslog(LOG_ERR, "Peek failed: %d", ret);
124
125
0
  finish(ret);
126
127
0
  EH_END();
128
0
}
129